Published Properties

When writing a Component kind definition, it's very common to create a set of published properties. These properties behave the same as any other kind properties, with the added benefit that getter and setter functions are automatically generated for them. The getter and setter functions form an important part of a component's public API.

(Note: If you haven't yet read Enyo Basics - Kinds, Components, and Controls, you should do so before continuing.)

Here is the start of a simple star-rating control that publishes two properties. We'll complete it step-by-step.

enyo.kind({
  name: "Stars",
  kind: "Control",
  published: {
      stars: 2.5,
      starWidth: 18
  }
});

Since the stars and starWidth properties are published, getter and setter functions are generated for them. They are:

  • setStars(inStars)
  • getStars
  • setStarWidth(inStarWidth)
  • getStarWidth

Notice the function naming: the property name is capitalized and prefixed with "get" or "set".

The getter function will, by default, return the current value of the given property. For example, getStars will return this.stars. You can override this function to return a different value or perform whatever processing should occur when the property is retrieved.

The setter function will, by default, set the value of the given property. For example, setStars(inStars) will set this.stars = inStars. Frequently, you'll want setters to trigger side effects. To implement these, rather than overriding the setter directly, implement a "changed" method. This method will be called automatically if it exists. Its name is formed by appending "Changed" to the property name; in this case, it would be "starsChanged". The property changed method is called with the old value of the property--i.e., starsChanged(inOldStars). The current value of the property is already available in this.stars.

Here is the example from above with the starsChanged method implemented. When setStars is called, the value of this.stars is changed and starsChanged is called automatically, updating the control's display:

enyo.kind({
  name: "Stars",
  kind: "Control",
  published: {
      stars: 2.5,
      starWidth: 18
  },
  components: [
      {name: "redStars", className: "opus-stars-red"}
  ],
  starsChanged: function() {
      var w = Math.floor(this.stars * this.starWidth) + "px"
      this.$.redStars.applyStyle("width", w);
  }
});

Now, if an application creates a Stars control called "myStars", calling myStars.setStars(5) will set myStars.stars = 5 and update the display to show five stars.

There's just one more thing to add to the Stars control to make it fully functional.

It's common to perform initialization for a property when a component is created. In this case, if the configuration block for a Stars control specifies a value for the stars property, we want the control to render with the correct number of stars. This initialization is not automatic. This is so that the component writer can customize what occurs when the component is created. That said, it's typically a good practice to call the property's changed method in the component's create method.

Here's the complete Stars control with that addition:

enyo.kind({
  name: "Stars",
  kind: "Control",
  published: {
      stars: 2.5,
      starWidth: 18
  },
  components: [
      {name: "redStars", className: "opus-stars-red"}
  ],
  create: function() {
      this.inherited(arguments);
      this.starsChanged();
  },
  starsChanged: function() {
      var w = Math.floor(this.stars * this.starWidth) + "px"
      this.$.redStars.applyStyle("width", w);
  }
});

Note: The property publishing system for Components is implemented by enyo.Object, the kind from which enyo.Component is derived. The other attributes typically considered to be defining characteristics of Components--the fact that they have owners, they can create children, can fire and respond to events, and so on--are not present in the Object kind.