Fabulous.CodeGen

Root

{
    "assemblies": [
        "path/to/A.dll",
        "path/to/B.dll"
    ],
    "outputNamespace": "My.Namespace",
    "types": [
        // See Type
    ]
}
FieldTypeRequiredDescription
Assembliesstring array✅ YesPaths to dlls containing controls (can be relative to working directory)
OutputNamespacestring✅ YesNamespace under which all the generated code will be added
TypesType array✅ YesAll types to bind

Type

{
    "type": "Xamarin.Forms.ListView",
    "customType": "Fabulous.XamarinForms.CustomListView",
    "canBeInstantiated": true,
    "name": "ListView",
    "properties": [
        // See Property
    ],
    "events": [
        // See Event
    ],
    "attachedProperties": [
        // See Attached Property
    ]
}
FieldTypeRequiredDescription
Typestring✅ YesFull name of a control inside one of the dlls to bind
CustomTypestring❌ NoIf specified, this type will be used when instantiating this control instead of the binded type. Not necessary that the control exists at generation time
CanBeInstantiatedboolean❌ NoIndicates if the code generator should provide a public constructor for this type. If not specified, the value defaults to true
Nameboolean❌ NoThe name that will be used when generating code (e.g. View.MyCustomControl()). If not specified, the name will be inferred from the Type field
PropertiesProperty array❌ NoAll properties of this control to include in the code generation
EventsEvent array❌ NoAll events of this control to include in the code generation
AttachedPropertiesAttachedProperty array❌ NoAll attached properties of this control to include in the code generation

Property

{
    "source": "Source",
    "name": "Name",
    "uniqueName": "UniqueName",
    "shortName": "shortName",
    "defaultValue": "DefaultValue",
    "elementType": "ElementType",
    "inputType": "InputType",
    "modelType": "ModelType",
    "convertInputToModel": "(fun input: InputType -> input :?> ModelType)",
    "convertModelToValue": "(fun model: ModelType-> model :?> ValueType)",
    "updateCode": "(fun prev curr target -> ())"
}
FieldTypeRequiredDescriptionRemarks
Sourcestring❓DependsName of the property to include (and overwrite)
Namestring❓DependsName of the property used in the generated code (e.g. buttonViewElement.MyProperty(value))If not specified, Source will be used instead
UniqueNamestring❌ NoName to uniquely identify the property in the generated codeUse with caution. If not specified, Type and Name will be concatenated to create a unique name. (e.g. ButtonText). Subject to optimization
ShortNamestring❌ NoName (lower camel case) to use in ViewElement constructor (e.g. View.Button(myProperty=value))If not specified, Name will be used in lower camel case
DefaultValuestring❓DependsDefault value to apply to the property if none is given by the user (e.g. 0.0f)
ElementTypestring❓Depends(Apply only if property is a collection) Full name of the item type of the collectionIf null, the property is not considered to be a collection
InputTypestring❓DependsType expected in the constructor (e.g. string => View.Button(text = "some string"))
ModelTypestring❌ NoType as which the value will be stored in the ViewElement attributes dictionaryMake sure this type is efficient
ConvertInputToModelstring❌ NoFunction to convert the input value to the model typeExpects a signature of type 'Input -> 'Model. Function can be written directly inside the json, or make a reference to a function. If not specified, no conversion will be applied.
ConvertModelToValuestring❌ NoFunction to convert the model value to the expected type of the real propertyExpects a signature of type 'Model -> 'Value. Function can be written directly inside the json, or make a reference to a function. If not specified, no conversion will be applied.
UpdateCodestring❌ NoFunction to use instead of the generated view diffing for this propertyExpects a signature of type prev: ViewElement -> curr: ViewElement -> target: ControlType -> unit. Function can be written directly inside the json, or make a reference to a function. If not specified, the default view diffing code will be used.

There is 3 different categories of property:

  • Existing scalar property: A property present in one of the dlls to include with a simple data type
  • Existing collection property: A property present in one of the dlls to include which is a collection (e.g. Xamarin.Forms.View list)
  • Dummy property: A non-existent property to include which can be either of type scalar or collection

See examples for these categories below.

Event

{
    "source": "TextChanged",
    "name": "TextChanged",
    "uniqueName": "EntryTextChanged",
    "shortName": "textChanged",
    "inputType": "Xamarin.Forms.TextChangedEventArgs -> unit",
    "modelType": "System.EventHandler<Xamarin.Forms.TextChangedEventArgs>",
    "convertInputToModel": "(fun f -> System.EventHandler<Xamarin.Forms.TextChangedEventArgs>(fun _sender _args -> f args))"
}
FieldTypeRequiredDescriptionRemarks
Sourcestring❓DependsName of the event to include (and overwrite)
Namestring❓DependsName of the event used in the generated code (e.g. entryViewElement.TextChanged(value))If not specified, Source will be used instead
UniqueNamestring❌ NoName to uniquely identify the event in the generated codeUse with caution. If not specified, Type and Name will be concatenated to create a unique name. (e.g. EntryTextChanged). Subject to optimization
ShortNamestring❌ NoName (lower camel case) to use in ViewElement constructor (e.g. View.Button(myProperty=value))If not specified, Name will be used in lower camel case
InputTypestring❓DependsType expected in the constructor (e.g. Xamarin.Forms.TextChangedEventArgs -> unit => View.Button(textChanged = (fun args -> ())))Expects a function
ModelTypestring❓DependsType as which the value will be stored in the ViewElement attributes dictionaryExpects an EventHandler
ConvertInputToModelstring❓DependsFunction to convert the input value to the model typeExpects a signature of type 'Input -> 'Model. Function can be written directly inside the json, or make a reference to a function. If not specified, no conversion will be applied.

AttachedProperty

{
    "source": "Source",
    "name": "Name",
    "uniqueName": "UniqueName",
    "defaultValue": "DefaultValue",
    "elementType": "ElementType",
    "inputType": "InputType",
    "modelType": "ModelType",
    "convertInputToModel": "(fun input -> input :?> Model)",
    "convertModelToValue": "(fun model -> model :?> Value)",
    "updateCode": "(fun prev curr target -> ())"
}
FieldTypeRequiredDescriptionRemarks
Sourcestring❓ DependsName of the attached property to include (and overwrite)
TargetTypestring❌ NoType to which this attached property will be applied toIf not specified, a default base target type will be applied
Namestring❓ DependsName of the property used in the generated code (e.g. buttonViewElement.MyProperty(value))If not specified, Source will be used instead
UniqueNamestring❌ NoName to uniquely identify the property in the generated codeUse with caution. If not specified, Type and Name will be concatenated to create a unique name. (e.g. ButtonText). Subject to optimization
DefaultValuestring❓ DependsDefault value to apply to the property if none is given by the user (e.g. 0.0f)If not specified, Name will be used in lower camel case
ElementTypestring❓ Depends(Apply only if attached property is a collection) Full name of the item type of the collectionIf null, the attached property is not considered to be a collection
InputTypestring❓ DependsType expected in the constructor (e.g. string => View.Button(text = "some string"))
ModelTypestring❌ NoType as which the value will be stored in the ViewElement attributes dictionaryMake sure this type is efficient
ConvertInputToModelstring❌ NoFunction to convert the input value to the model typeExpects a signature of type 'Input -> 'Model. Function can be written directly inside the json, or make a reference to a function. If not specified, no conversion will be applied.
ConvertModelToValuestring❌ NoFunction to convert the model value to the expected type of the real propertyExpects a signature of type 'Model -> 'Value. Function can be written directly inside the json, or make a reference to a function. If not specified, no conversion will be applied.
UpdateCodestring❌ NoFunction to use instead of the generated view diffing for this propertyExpects a signature of type prev: ViewElement -> curr: ViewElement -> target: ControlType -> unit. Function can be written directly inside the json, or make a reference to a function. If not specified, the default view diffing code will be used.

Examples

Example properties

Existing scalar property

{
    "source": "Margin",
    "name": "Margin",
    "uniqueName": "VisualElementMargin",
    "shortName": "margin",
    "inputType": "InputTypes.Thickness",
    "modelType": "Thickness",
    "convertInputToModel": "ViewConverters.convertThickness",
    "convertModelToValue": null
}
FieldTypeRequired
Sourcestring✅ Yes
Namestring❌ No
UniqueNamestring❌ No
ShortNamestring❌ No
InputTypestring❌ No
ModelTypestring❌ No
ConvertInputToModelstring❌ No
ConvertModelToValuestring❌ No
UpdateCodestring❌ No

Existing collection property

{
    "source": "ItemsSource",
    "name": "Items",
    "uniqueName": "GridItems",
    "shortName": "items",
    "elementType": "Xamarin.Forms.View",
    "inputType": "ViewElement list",
    "modelType": "ViewElement array",
    "convertInputToModel": "Array.ofList"
}
FieldTypeRequiredRemarks
Sourcestring✅ Yes
Namestring❌ No
UniqueNamestring❌ No
ShortNamestring❌ No
ElementTypestring❓ DependsUsually automatically detected by the AssemblyReader step. If correct, no need to specify it.
InputTypestring❌ No
ModelTypestring❌ No
ConvertInputToModelstring❌ No
ConvertModelToValuestring❌ No
UpdateCodestring❌ No

Dummy property

{
    "source": null,
    "name": "Name",
    "inputType": "InputType"
}
FieldTypeRequiredRemarks
Sourcestring❌ NoMust be null or not declared
Namestring✅ Yes
UniqueNamestring❌ No
ShortNamestring❌ No
ElementTypestring❓ DependsMust be declared if property is a collection
InputTypestring✅ Yes
ModelTypestring❌ No
ConvertInputToModelstring❌ No
ConvertModelToValuestring❌ No
UpdateCodestring❌ No