# The component Binding

The `component` binding injects a specified component into an element using the `data-bind` syntax. This is an alternative to using a `<custom-element></custom-element>`.

## Example

    <h4>First instance, without parameters</h4>
    <div data-bind='component: "message-editor"'></div>

    <h4>Second instance, passing parameters</h4>
    <div data-bind='component: {
      name: "message-editor",
      params: { initialText: "Hello, world!" }
    }'></div>

    fw.components.register('message-editor', {
      viewModel: function(params) {
        this.text = fw.observable(params && params.initialText || '');
      },
      template: 'Message: <input data-bind="value: text" /> '
              + '(length: <span data-bind="text: text().length"></span>)'
    });

    fw.applyBindings();

Note

In more realistic cases, you would typically load component viewmodels and templates from external files, instead of hardcoding them into the registration. See an example and registration documentation.

## Usage

There are two ways to use the `component` binding:

- Shorthand syntax

  If you pass just a string, it is interpreted as a component name. The named component is then injected without supplying any parameters to it. Example:

      <div data-bind='component: "my-component"'></div>

  The shorthand value can also be observable. In this case, if it changes, the `component` binding will dispose the old component instance, and inject the newly-referenced component. Example:

      <div data-bind='component: observableWhoseValueIsAComponentName'></div>

- Full syntax

  To supply parameters to the component, pass an object with the following properties:

  - `name`

    The name of the component to inject. Again, this can be observable.

  - `params`

    An object that will be passed on to the component. Typically this is a key-value object containing multiple parameters, and is typically received by the component's viewmodel constructor.

      <div data-bind='component: {
        name: "shopping-cart",
        params: { mode: "detailed-list", items: productsList }
      }'></div>

  Note

  Whenever a component is removed (either because the `name` observable changed, or because an enclosing control-flow binding removed the entire element), the removed component is disposed.

### Template-only components

Components usually have viewmodels, but they don't necessarily have to. A component can specify just a template.

In this case, the object to which the component's view is bound is the `params` object that you passed to the `component` binding. Example:

    fw.components.register('special-offer', {
      template: '<div class="offer-box" data-bind="text: productName"></div>'
    });

... can be injected with:

    <div data-bind='component: {
      name: "special-offer-callout",
      params: { productName: someProduct.name }
    }'></div>

... or, more conveniently, as a custom element:

    <special-offer params='productName: someProduct.name'></special-offer>

### Containerless Usage

Sometimes you may want to inject a component into a view without using an extra container element. You can do this using containerless control flow syntax, which is based on comment tags. For example,

    <!-- ko component: "message-editor" -->
    <!-- /ko -->

... or passing parameters:

    <!-- ko component: {
      name: "message-editor",
      params: { initialText: "Hello, world!", otherParam: 123 }
    } -->
    <!-- /ko -->

The `<!-- ko -->` and `<!-- /ko -->` comments act as start/end markers, defining a "virtual element" that contains the markup inside. Footwork understands this virtual element syntax and binds as if you had a real container element.

### Passing Markup To Components

The element you attach a `component` binding to may contain further markup. For example,

    <div data-bind="component: { name: 'my-special-list', params: { items: someArrayOfPeople } }">
      <!-- Look, here's some arbitrary markup. By default it gets stripped out
           and is replaced by the component output. -->
      The person <em data-bind="text: name"></em> is <em data-bind="text: age"></em> years old.
    </div>

Although the DOM nodes in this element will be stripped out and not bound by default, they are not lost. Instead, they are supplied to the component (in this case, `my-special-list`), which can include them in its output however it wishes.

This is useful if you want to build components that represent "container" UI elements, such as grids, lists, dialogs, or tab sets, which need to inject and bind arbitrary markup into a common structure. See a complete example for custom elements, which also works without custom elements using the syntax shown above.