@progress/sitefinity-widget-designers-sdk
TypeScript icon, indicating that this package has built-in type declarations

0.1.6 • Public • Published

Sitefinity widget designers SDK

This package aims to create a parity for widget designer generation similar to the autogenerated widget designers in Sitefinity. Due to some limitations in Typescript and Javascript, there are several cases where additional data must be provided (see usage guide). Full API documentation could be found in the api.md in the source.

Intallation

via NPM:

npm i @progress/sitefinity-widget-designers-sdk --save

via yarn:

yarn add @progress/sitefinity-widget-designers-sdk

The package relies on the Typescript decorators, which requires adding support for decorators to your tsconfig.json file:

{
    "compilerOptions": {
        ...
        "experimentalDecorators": true
        }
}

Concept

The metadata, generated from this package, aims to equal the metadata generated by Sitefinity or the ASP.NET Core external renderer and replace the usage of JSON metadata files in external renderers.

Usage

Exctracting the metadata

import { EntityMetadataGenerator, MetadataModel } from "@progress/sitefinity-widget-designers-sdk";

const designerMetadata: MetadataModel = EntityMetadataGenerator.extractMetadata(widgetEntity);

Extracting default values from the metadata

The the metadata generator will go through the designer JSON definition, extract and parse the default value for each property is such is set. Normally the return type would match the type definition of the widget entity model.

import { EntityMetadataGenerator } from "@progress/sitefinity-widget-designers-sdk";

const defaultValues: { [key: string]: any } = EntityMetadataGenerator.extractDefaultValues(designerMetadata);

Parsing serialized widget model values

Sitefinity preserves the widget data on the server in stringified JSON form so when it is received, a parsing depending on the property type is necessary to match the entity model properties' types.

import { EntityMetadataGenerator } from "@progress/sitefinity-widget-designers-sdk";

const deserializedValues: { [key: string]: any } = EntityMetadataGenerator.parseValues(valuesFromServerCall, designerMetadata);

Creating a widget entity and property metadata

The widget model should be decorated using the WidgetEntity decorator.

import { WidgetEntity } from "@progress/sitefinity-widget-designers-sdk";

@WidgetEntity("SitefinitySection", "Section")
export class SectionEntity {
    @Category('QuickEdit')
    CssSystemGridSize: number = 12;
}

Properties that have complex models as types need their data models explicitly specified (while in C# these types and their subproperties would be generated OOB). For more details on complex objects see here

import { Model, WidgetEntity} from "@progress/sitefinity-widget-designers-sdk";

@WidgetEntity("ComplexWidget", "Complex Widget")
class EntityWithComplexProperties {
    @DisplayName("Complex property")
    @DataModel(ComplexPropModel)
    ComplexProperty?: ComplexPropModel;
}

@Model()
class ComplexPropModel {
    @DataType("string")
    ChildString: string | null = null;
}

is the same as in C#

public class EntityWithComplexProperties {
    [DisplayName("Complex property")]
    public ComplexPropModel ComplexProperty { get; set; }
}

public class ComplexPropModel {
    public string ChildString { get; set; }
}

Specifics

Default values

The default value of the properties would be taken either from the DefaultValue decorator or a default value set to the property in the class declaration:

@DisplayName("Number prop")
@DefaultValue(42)
@DataType("number")
NumberProperty: number;
// DeafultValue="42" Type="number"

If a default value is set to basic types, the DataType decorator can be omitted. The following code would produce the same output:

@DisplayName("Number prop")
NumberProperty: number = 42;
// DeafultValue="42" Type="number"

Property display configuration

Sections can be arraged either manually or via the SectionsOrder class decorator.

Properties can be arranged in sections in the autogenerated designers and ordered by a given index via the ContentSection decorator.

Sections can be separed in categories: Basic, Advanced, QuickEdit. Setting the category to the property will move the property there and create a section for it in that category.

Properties can be given several types of description via the Description and DescriptionExtended decorators.

@WidgetEntity('CustomEntity', 'Custom entity')
@SectionsOrder('First section', 'Second section')
class Entity {
    @ContentSection('Second section', 0)
    SecondSectionFirstProperty: any;
    
    @ContentSection('Second section', 1)
    SecondSectionSecondProperty: any;

    @ContentSection('First section', 0)
    @Description('simple description')
    FirstSectionFirstProperty: any;

    @Category('Advanced')
    @DescriptionExtended({
        Description: '...',
        InlineDescription: '...',
        InstructionalNotes: '...'
    })
    FirstPropertyAdvancedCategoryNewSection: any;
}

Field type

The property editor field is defined via the DataType decorator. Besides the basic types such as string, number, bool/boolean, there are some predefined types in the KnownFieldTypes enum as well as the several variations in the ComplexType enum. Types that are a variation of choices should have a Choice decorator defined as well.

@DataType('string')
StringProperty: string | null = null;

// @DataType('string') for basic types the decorator can be omitted if there is a default value of the same type set
StringProperty: string = 'default value';

@DataType(KnownFieldTypes.Choices)
@Choice([{Title: 'First choice', Value: 'first'}, {Title: 'Second choice', Value: 'second'}])
ChoiceProperty: string | null = null;

// checkbox
@DataType(KnownFieldTypes.CheckBox)
YesNoProperty: boolean = false;

// chip choice
@DataType(KnownFieldTypes.ChipChoice)
@Choice({Choices: [
    {Title:'Yes', Name: 'Yes', Value: 'True', Icon: null},
    {Title:'No', Name: 'No', Value: false, Icon: null}
]})
ChipChoiceSingle: boolean = true;

Validation

Property values can be validated on the front end based on decorators set in the entity. Most of them can receive and custom validation failed error message.

  • Required
  • Readonly
  • Range
  • MinLength
  • MaxLength
  • RegularExpression:
    • Url (predefined regexp)
    • EmailAddress (predefined regexp)
  • DecimalPlaces (for floating point numbers)
  • StringLength

Associated content or media items

A property can refer to a content item of any of the types that are found or created in Sitefinity. The autogenerated designer will display a content selector for that content type. The full type name should be used - e.g. for pages: Telerik.Sitefinity.Pages.Model.PageNode

Related content and media
@Content({
    Type: 'Telerik.Sitefinity.Pages.Model.PageNode',
    AllowMultipleItemsSelection: false
})
SelectedPage: MixedContentContext = null;

// Media item is shorthand for Content
@MediaItem('images', true)
SelectedMedia: MixedContentContext = null;

@Content({
    Type: 'Telerik.Sitefinity.Libraries.Model.Image',
    AllowMultipleItemsSelection: false
})
FullDecoratorSelectedMedia: MixedContentContext = null;
Taxonomy
@TaxonomyContent({Type: 'Taxonomy_Tags'})
SelectedTags: MixedContentContext = null

// or 

@TaxonomyContent({Type: 'Tags'})
ShorthandSelectedTags: MixedContentContext = null

Conditional visibility

Fields can be shown or hidden based on other property values using the ConditionalVisibility decorator.

FirstProperty: string = '';

@ConditionalVisibility({
    conditions: [{
        fieldName: 'FirstProperty',
        operator: 'Equals',
        value: 'show second property'
    }]
})
SecondProperty: string = '';

Complex objects

In the autogenerated designers in Sitefinity there are several ways to define and to represent properties with complex object types.

@DataModel(PropModel)
// @DataType(ComplexType.Complex)
ComplexObjProp: PropModel = null; // => renders a section with the model

@DataModel(PropModel)
// @DataType(ComplexType.Complex)
@TableView("TableTitle")
ComplextTableProp: PropModel = null; // => renders the model as a table

@DataModel(PropModel)
@DataType(ComplexType.Enumerable)
MultipleComplexObj: PropModel[] = null; // renders editable rows for each instance of the model

@DataModel(PropModel)
// @DataType(ComplexType.Enumerable)
@TableView({ Reorderable: true, Selectable: true, MultipleSelect: true })
MultipleComplexObj: PropModel[] = null; // renders full editable table with a row for each instance of the model
...

@Model()
class PropModel {
    stringProp: string = "default-value";
    numberProp: number = 13;
    ...
}

Collections

Having a properties of collection types, it should be explicitly specified:

Array

Currently arrays are supported for objects/classes and string types. Other types would be rendered as a simple string field.

import { ComplexType, DataModel, DataType } from "@progress/sitefinity-widget-designers-sdk";

// would receive Type="enumerable"
@DataType(ComplexType.Enumerable, "string")
ValidStringCollection: string[] = null;

// would receive Type="enumerable"
@DataModel("string")
@DataType(ComplexType.Enumerable)
AlsoValidStringCollection: string[] = null;

// would receive Type="enumerable"
// with TypeChildProperties of the DataModel
@DataModel(ObjectModel)
@DataType(ComplexType.Enumerable)
ObjectCollection: ObjectModel[] = null

// invalid properties
// would receive Type=null
@DataType(ComplexType.Enumerable)
InvalidCollection: boolean[] | number[] = null;
Dictionary

Currently a collection of type dictionary is supported only when LengthDependsOn property decorator is also present and the value type is an object/class. Otherwise the field would be rendered as a simple string field. For collections of objects that don't depend on another property, we suggest using an array.

import { ComplexType, DataType, Model } from "@progress/sitefinity-widget-designers-sdk";

@DataModel(DictValue)
@DataType(ComplexType.Dictionary)
@LengthDependsOn("PropName", "PropDisplayName", "PropTitle")
ObjectDictionary: { [key: string]: DictValue } = null;

....

@Model()
class DictValue {
    @DataType("number")
    Int: number;

    @DataType("string")
    Str: string;
}

Package Sidebar

Install

npm i @progress/sitefinity-widget-designers-sdk

Weekly Downloads

378

Version

0.1.6

License

LICENSE.txt

Unpacked Size

490 kB

Total Files

194

Last publish

Collaborators

  • progress