# Nesting Components

In component-based frameworks like Angular, React we create a root component and build a tree. With ngBackbone we can do the same. Let's create a new child component `foo.ts`:

```javascript
import { Component, View } from "ng-backbone";

@Component({
  el: "ng-foo",
  template: `Hello, it's Foo`
})

export class FooView extends View {
  initialize(){
    this.render();
  }
}
```

Then we add its sibling `bar.ts`

```javascript
import { Component, View } from "ng-backbone";

@Component({
  el: "ng-bar",
  template: `Hello, it's Bar`
})

export class BarView extends View {
  initialize(){
    this.render();
  }
}
```

As you can see from the code both of the components render themselves during initialization. In the root `app.ts` we can use `views` map to refer to the nesting components:

```javascript
import { Component, View } from "ng-backbone";
import { FooView } from "./foo";
import { BarView } from "./bar";

@Component({
  el: "ng-hello",
  views: {
    foo: FooView,
    bar: BarView
  },
  template: `<ng-foo></ng-foo> <ng-bar></ng-bar>`
})

class AppView extends View {
}

let app = new AppView();
app.render();
```

Here we specified the locations for the child components in the template by placing there elements `ng-foo` and `ng-bar`. These are the elements we have bound our nested components to.

After compiling `app.ts` we get in the browser both the nesting components rendered within the root: ![](https://265109865-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LdyKJ-wwTI6fjCWU9_0%2F-LdyKJXH0z26CupROfdA%2F-LdyKKTSiFMko93Z44HW%2Fsh-01.PNG?generation=1556897685861409\&alt=media)

## Child Component and Construction Options

Well, what if we need to pass specific constructor arguments to a nesting component? Not a problem. We can specify a subordinated component as an array where the constructor goes in the first element and view options in the second:

```javascript
@Component({
  el: "ng-hello",
  views: {
    foo: [ FooView, { name: "foo" } ],
    bar: [ BarView, { name: "bar" } ]
  },
  template: `<ng-foo></ng-foo> <ng-bar></ng-bar>`
})
```

> Child components get constructed after the parent first rendering. Thus they can bind to the elements of the parent template. Besides construction ngBackbone also takes care about destruction. Whenever `remove()` method is called on the parent, this method is being invoked per each child recursively.

## Accessing Sub-components

Within parent component child ones are available in `views` map. You can access the instance of a sub-component as `this.views.get( "name" )`. Thus we obtain the control over child component from the parent:

```javascript
@Component({
  el: "ng-hello",
  events: {
    "click [data-bind=toggleFoo]" : "toggleFoo",
    "click [data-bind=toggleBar]" : "toggleBar"
  },
  views: {
    foo: FooView,
    bar: BarView
  },
  template: `
  <button data-bind="toggleFoo">Show Foo</button>
  <button data-bind="toggleBar">Show Bar</button>
  <ng-foo></ng-foo> <ng-bar></ng-bar>`
})

class AppView extends View {
  toggleFoo(){
    this.views.get( "foo" ).toogle();
  }
  toggleBar(){
    this.views.get( "bar" ).toogle();
  }
}
```

## Communicating between Parent and Child

As we just examined the parent component has the links to child ones. But every child component also has a link to the parent (`this.parent`). We can use it to implement bi-directional communication.

Let's write a child component that has a bound `echo` model. The template renders `echo.msg`. When the component initializes it changes `echo.msg` of it's parent, assuming the parent has similar model:

*child.ts*

```javascript
import { Component, View, Model } from "ng-backbone";

@Component({
  el: "ng-child",
  models: {
    echo: new Model({
      msg: ""
    })
  },
  template: `<h2>It's Child</h2>
  <p>Echo: <output data-ng-text="echo.msg"></output></p>
  `
})

export class ChildView extends View {
  initialize(){
    this.render();
    this.parent.models.get( "echo" ).set( "msg", "Hello, it's Child" );
  }
}
```

Now we create the parent component. During initialization it also changes the model of the child.

*parent.ts*

```javascript
import { Component, View, Model } from "ng-backbone";
import { ChildView } from "./child";

@Component({
  el: "ng-parent",
  views: {
    child: ChildView
  },
  models: {
    echo: new Model({
      msg: ""
    })
  },
  template: `<h2>It's Parent</h2>
  <p>Echo: <output data-ng-text="echo.msg"></output></p>
  <ng-child></ng-child>
  `
})

export class ParentView extends View {
  initialize(){
    this.render();
    let echo = this.views.get( "child" ).models.get( "echo" );
    echo.set( "msg", "Hello, it's Parent" );
  }
}

new ParentView();
```

When we compile the code and run it a browser, we see that parent received and displayed the message from child and vice versa.

![Communication between parent and child](https://265109865-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LdyKJ-wwTI6fjCWU9_0%2F-LdyKJXH0z26CupROfdA%2F-LdyKKT_h9RzL87QhhB9%2Fsv-05.PNG?generation=1556897685719743\&alt=media)

## Maintaining bindings on parent view change

Let's say we have an imaginary task. We have to create a list where every item has own view. So as for items the example view may look like:

```javascript
  @Component({
    el: "ng-item",
    template: "it's item"
  })
  class ItemView extends View {
    initialize(){
      this.render();
    }
  }
```

The parent (list) view has a bound collection named `items` and a subview named also `items`. As you remember we expect subview binding to `ng-item` element.

```javascript
  let items = new Collection([ new Model() ]);
  @Component({
    tagName: "ng-list",
    template: "<ng-item data-ng-for=\"let item of items\"></ng-item>",
    collections: {
      items: items
    },
    views: {
      items: ItemView
    }
  })
  class ListView extends View {
    initialize(){
      this.render();
    }
  }
```

Initially the collection has just a single element and on render we have `<ng-list><ng-item>it's item</ng-item></ng-list>`

```javascript
  let list = new ListView();
  list.views.getAll( "foo" ).length; // 1
  list.views.get( "foo" ); // ItemView
```

With method `list.views.getAll( "foo" )` we can access the array of bound ItemView instances. Here it consists of one element. However let's see what happens if we change the collection:

```javascript
  items.add([ new Model() ]);
  view.on( "component-did-update", () => {
    list.views.getAll( "foo" ).length; // 2
    list.views.get( "foo", 0 ); // ItemView
    list.views.get( "foo", 1 ); // ItemView
    done();
  });
```

The method `list.views.getAll( "foo" )` indicates that we have now 2 subview instances matching `ng-item` element. We can access a particular instance like `list.views.get( "foo", index )`
