G Suite Business customers can preview App Maker. Ask your domain admin to apply for early access.

Properties and Bindings

One of the most common tasks when developing an application with a GUI is keeping the user interface and the data in sync. For example, suppose you use conventional development tools to create a web application for browsing and editing customer records. Without App Maker, you'd have to develop a way keep the application UI and the database records in sync in the following ways:

  1. Update every UI element that displays data when the next record in the database is requested.

  2. Add change listeners to all UI elements to ensure that the user's changes are reflected in the customer record.

  3. Update the current customer record to receive the new data.

This is a lot of boilerplate to write and maintain, which is cumbersome if you're already a programmer and might be a major roadblock if you're not.

With App Maker, instead of having to write all that boilerplate, you use bindings to indicate that a property on the customer record and a property of a widget must be kept in sync. And you do all of this in an easy-to-use visual interface. That's it: App Maker does all the rest of the work for you.

Beyond this common scenario, App Maker bindings do more than just keep UI elements in sync with underlying values. You can use an App Maker binding to keep any two App Maker properties in sync, such as the email of the current logged in user, and a datasource query parameter. In fact, because almost anything in App Maker has bindings — models, datasources, widgets, and scripts — you can use bindings across a variety of App Maker properties.

Properties

Very simply, a property is a named value of an App Maker object. You can get and set the values of properties in App Maker, and most App Maker objects have properties that you can access from parts of your application.

You can set properties in many ways:

  • in the App Maker UI—when you set the name of a widget
  • via a binding—when one property changes to reflect updates from another property
  • in a script—you can set a property with JavaScript

You can access a variety of properties:

  • fields in database records
  • the email address for the currently logged-in user
  • widget attributes such as position, name, or value

In fact, properties are found all over App Maker, with the most common place being the Property Editor:

and the binding chooser:

Objects

Let's dig deeper into our exploration of properties with a discussion of objects. Objects are the "things" that make up App Maker and App Maker applications, and just about everything in App Maker is an object. What are these things? They are the widgets that make up your UI, the records that represent your data, the data source objects that read and write your data for you, and much more. Even your application itself is an object.

For example, a Text Area widget is an App Maker object with several properties, including name and label. A data record is an application object which has properties that you define, such as a customer record with a name property.

Types

All App Maker properties have a data type, which means that they only accept specific kinds of values, like numbers or strings. Many properties have simple types like string, number, or boolean, but some properties have complex types. For example, the parent property of a widget is also a widget and so is typed as Widget.

Paths

App Maker uses a path notation to refer to properties when referencing them in bindings, or in scripts. For example, a data model object named Person with a property named Name, would be referenced as Person.Name.

Undefined

Path and property values can be undefined. This is different from being null. An example of an undefined property is a record relation property that has not been loaded yet. A path such as datasource.item.Name is undefined if its last property (Name) is undefined, or if any of its parts such as datasource or item are undefined or null. In general, App Maker treats undefined values like null. However, input widgets will disable themselves if their values are set to undefined. For example, you can use the following script to clear the value of a text box and disable it:

textBox.value = undefined;

Example scenario

This example illustrates two complex properties — Person and Address. Each of these are special Types that you might define in a model you create. They are not built-in App Maker types.

Person
Property NameType
Namestring
Agenumber
AddressAddress
Address
Property NameType
Streetstring
Citystring
Zipstring

Because the Address property of Person is of type Address, you could use path notation to reference the location of a person with Person.Address.City.

Bindings

A binding is a mechanism for keeping two properties in sync. As an App Maker author, you will often declare that you want two properties—like the value of a text input and a field of a record—bound, and App Maker will automatically keep them in sync: when one property changes, the other will be set.

All properties in App Maker are observable, meaning that it's possible to listen for changes to a property. When a binding is made between two properties, the binding listens to, or observes, changes in each property, and when one changes, the other is updated.

A common binding example in App Maker is to bind a text input's value to the item property of a datasource. This binding is done using the App Maker property editor, but if we wrote the binding out, if would look like this:

@widget.text <-> @datasource.item.MyField

Type converter for bound values

A property has a type and a value. The value itself also has a type, which must match its property's value. For example, the Name property for a widget is a string type, so values for names are strings and cannot be treated as integers.

If you want to bind two properties together, they must either have the same type, or their values must be convertible from one type to the other. This is called type conversion.

For example, if you give a value of "6" to the Name property of a widget, this value of "6" is treated as a string, not a number. You could bind this property to another property that is of type integer, and the App Maker built-in type converter attempts to convert the value types between these two properties.

App Maker includes many built-in type conversions, so that most bindings will work. The converters work in both directions, and make their best attempt to convert a value from one type to the other.

FromToConditions
stringnumberOnly if from can be parsed as a number.
stringbooleanOnly if from is "true" or "false" (Case insensitive).
stringdateOnly if from is a date in YYYY-MM-DD format.
numberbooleanZero is converted to false and any other value to true
Array<A>Array<B>As long as A and B are compatible.

Transformers

Sometimes, you would like to bind two properties with some custom data conversion between them. For example, you might want to bind a field in a record to a text field in the UI, but you want the user input to be trimmed of whitespace before being saved in the database. Or you might want to convert a date to a string using a different date pattern than the one used by the default App Maker type conversion. Transformers allow you specify transformations on property paths. Each transformer takes an input value and produces an output value and most transformers can also take output values and convert them back to input values. These transformations can be chained together. For example, to trim whitespace from inputs and outputs for a string path, you might bind the value property of a text field to the Name field of a datasource record:

@value <-> @datasource.item.Name#trim()

Or you can specify custom date to string formatting when binding a text field value property to a date field timestamp in the database:

@value <--> @datasource.item.TimeStamp#formatDate('yyyy/MM/dd HH:mm:ss');

Transformers can be chained together:

@value <-> @datasource.item.Name#nullToEmpty()#trim()

You can find a list of all the built-in transformers here.

Transformers can also be applied to elements of an array rather than the array itself. For example, if you are populating a Dropdown widget's name property with items from a projection. The syntax is the same, but use two hash marks instead of one.

@names <-> @datasources.items..TimeStamp##formatDate('yyyy/MM/dd HH:mm:ss')

Top-level properties in bindings

When you bind the property of an object (such as a widget name), you'll use the binding picker to navigate through the available properties. App Maker automatically adjusts the available properties depending on the object that you are binding from. This simplifies the process of binding to certain common properties. For example, if you bind a value for a Button widget, the binding picker automatically defaults to the widget's datasource.item property, which usually contains fields of a model.

However, you might want to bind a widget or other object to something other than the automatically provided suggestions in the binding picker. For that, it's helpful to understand the two general categories of properties that you can navigate through when binding objects in your application.

Globally available properties

You can bind to any property of your application. These properties are generally accessed through the app object. When binding, all properties of the app objects are categorized, and exposed for bindings. See the app object API documentation for detailed documentation of all properties.

Properties available to widgets

A widget can be bound to all the properties of the app object, and to two additional properties:

  • widget—the widget itself.
  • datasource—the datasource for the widget, which is the most common object to bind to a widget. This is also available as @widget.datasource, but for convenience, datasource is shown in the binding picker in the UI editor.

Binding Expressions

Sometimes it's not enough to bind two properties directly together. By using expressions in the binding editor in the App Maker UI, you can combine bindings and JavaScript to transform a value that you are bound to. App Maker evaluates the expression any time one of the properties used in the expression changes. Note: this makes the binding one-way.

For example, suppose you have a Delete button named MyDeleteButton and you want to create a binding so that the button is disabled if there is no record in the database to delete. However, there's no property to directly represent that concept. We do have the enabled property and the property @datasource.item, and we know that if there is no item, the value of item is null. So with those pieces of information, we can make this binding:

@widget.enabled <-> @datasource.item != null

and the button will only be enabled when there's a record.

Additional Resources

For more information on creating binding expressions, see Binding Expressions and Client-side Scripting. For information on all the properties and methods available for widgets and client objects, see Widgets API and Client API.