> For the complete documentation index, see [llms.txt](https://dsheiko.gitbook.io/ng-backbone/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dsheiko.gitbook.io/ng-backbone/nesting_components.md).

# 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: ![](/files/-LdyKKTSiFMko93Z44HW)

## 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](/files/-LdyKKT_h9RzL87QhhB9)

## 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 )`


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dsheiko.gitbook.io/ng-backbone/nesting_components.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
