Forward Advance Learning

Making Angular 2 Components Receive Values (inputs)

Components are analogous to DOM nodes. Just as the behaviour of a DOM node can be affected by setting attributes on it, our components can also receive attributes (and property bindings) as inputs.

Attributes are the inputs of our components.

We tell our app it can receive inputs by setting an inputs attribute in the Component decorator, like so:

inputs: ["profile"]

Here's that in context:

var UserComponent = ng.core
.Component({
selector: "user",
inputs: ["profile"],
template:
`
<div>
user: {{profile}}
</div>
`
})
.Class({
constructor: function() {}
})

Passing the inputs in

We can pass inputs in several ways:

We can pass an attribute (which will come through as a literal)

<user profile="davey"></user>

We can pass a property from the parent component, which will be evaluated in it's current context:

<user [profile]="userProfile"></user>

If we want a string literal here, we can compose one in the expression:

<user [profile]="'mikey'"></user>

Or we could hardcode an object:

<user [profile]="{name: 'mikey'}"></user>

Finally we might use a curly expression to bind an expression to an attribute. Though this works, and may feel quite attractive, it is not the preferred way to do this. Changing an attribute may trigger a browser reflow, where the browser re-renders the page. This is an expensive thing and may slow down your app.

<user profile="{{name}}"></user>

Here's the above in context:

var AppComponent = ng.core
.Component({
selector: "app",
template:
`
<user [profile]="name"></user>
<user [profile]="'mikey'"></user>
<user profile="davey"></user>
<user profile="{{name}}"></user>
`
})
.Class({
constructor: function() {
this.name = 'stewey'
}
})

Exercise - Escape the Dungeon

Our dungeon game currently has four components:

  • app
    • location
    • protagonist
    • inventory

and three models:

  • Location
  • Protagonist
  • Inventory

Assign the models as properties of the app component, like so:

var AppComponent = ng.core
.Component({
selector: "app",
template:
``
})
.Class({
constructor: function() {
this.Location = {...}
this.Protagonist = {...}
this.Inventory = {...}
}
})

Make the Location, Protagonist and Inventory components receive their values from the app component.

We have a single source of truth, and we are passing the values down into the components where they are needed.