{"id":2044,"date":"2017-05-08T15:55:21","date_gmt":"2017-05-08T15:55:21","guid":{"rendered":"http:\/\/salientsoft.co.uk\/?p=2044"},"modified":"2018-10-10T17:15:57","modified_gmt":"2018-10-10T17:15:57","slug":"how-to-refer-to-child-component-instances-from-an-angular-component-class","status":"publish","type":"post","link":"https:\/\/salientsoft.co.uk\/?p=2044","title":{"rendered":"How to refer to child component instances from an Angular component class"},"content":{"rendered":"<p>With Angular, the component objects are automatically created and associated with their corresponding elements in the template.<\/p>\n<p>This raises the question then \u2013 if you want to refer to a child object from a parent component, how do you do it? There may be multiple child components of the same time in the parent component, so how do you get a reference to a specific one?<\/p>\n<p>As a contrast, when using JSF for example to refer to child component code, the parent managed bean (= component object in Angular) is actually responsible for declaring the managed bean objects for its children. On the page, the child component element will typically have a specific e.g. controller attribute where the managed bean for that child is passed in, e.g. as <em>&lt;child controller=#{controller.child}&gt;\u2026<\/em>&#160; where <em>controller.child<\/em>&#160; refers to the child property of the parent managed bean. In this way, unlike Angular, the object hierarchy is explicitly declared in the code.<\/p>\n<p>In Angular, there are a number&#160; of ways to do this, but in the end they all come down to using reference information from a particular template element to direct which object is required.<\/p>\n<p><em><strong>It is instructive to read the whole section on <\/strong><\/em><a href=\"https:\/\/angular.io\/docs\/ts\/latest\/guide\/template-syntax.html\"><em><strong>Angular template syntax<\/strong><\/em><\/a><em><strong> in the Angular docs, which includes all the binding techniques.<\/strong><\/em><\/p>\n<p>1\/ Passing an element reference in a method call from the template<\/p>\n<blockquote>\n<pre>&lt;ion-auto-complete id=&quot;location-search&quot; #locationSearch [dataProvider]=&quot;locationsAutoCompleteService&quot;<br \/>                   (itemSelected)=&quot;onItemClicked($event, locationSearch)&quot;&gt;&lt;\/ion-auto-complete&gt;<\/pre>\n<\/blockquote>\n<p>In this case, <em>(itemSelected)=&quot;onItemClicked($event, locationSearch)&quot; <\/em>is passing the element reference #locationSearch as the second argument to onItemClicked. This passes the reference to the component object for&#160; &lt;ion-auto-complete&gt;. (Note that in this case the first argument, $event, is the actual location object that was clicked in an autocomplete list).<\/p>\n<p>2\/ Using the <a href=\"https:\/\/angular.io\/docs\/ts\/latest\/api\/core\/index\/ViewChild-decorator.html\">@ViewChild<\/a> decorator in the parent class, passing it a child reference used in the template<\/p>\n<blockquote>\n<pre>export class AutoCompleteComponent {<br \/><br \/>  @Input() public dataProvider:   any;<br \/>  @Output() public itemSelected:  EventEmitter&lt;any&gt;;<br \/>  @ViewChild(Searchbar) searchBar: Searchbar;<\/pre>\n<\/blockquote>\n<p>In this case, the component only contains a single searchbar, so using a class reference is not ambiguous. If there were multiples, the first one would be taken. You can inject references to multiple children via <a href=\"https:\/\/angular.io\/docs\/ts\/latest\/api\/core\/index\/ViewChildren-decorator.html\">@ViewChildren<\/a> if there is more than one present \u2013 this gives you access to an array of them. <\/p>\n<p>Where you want to use a reference to a specific element, you can use @ViewChild with an element reference, e.g. in 1\/ above you would use&#160; #locationSearch to inject a referent to the &lt;ion-auto-complete #locationSearch &gt; element as follows:-<\/p>\n<blockquote>\n<pre>@ViewChild(\u2018#locationSearch\u2019) searchBar: Searchbar;<\/pre>\n<\/blockquote>\n<p>3\/ Another related technique is to make a method call in the template e.g. in an event call, using an element reference to another element in the component. This is detailed <a href=\"http:\/\/stackoverflow.com\/questions\/31013461\/call-a-method-of-the-child-component\">here<\/a>. Note that <em>&lt;child-component #f<\/em> contains the #f element reference, and the <em>inc()<\/em> method on the <em>#f<\/em> element is called from the button click event using <em>&lt;button (click)=\u201df.inc()\u201d&gt;<\/em><\/p>\n<blockquote>\n<pre><code>@Component({\n    selector: 'child-component',\n    inputs: ['bar'],\n    template: `&quot;{{ bar }}&quot; in child, counter  {{ n }}`\n})\nclass ChildComponent{\n    constructor () {\n        this.n = 0;\n    }\n    inc () {\n        this.n++;\n    }\n}\n\n@Component({\n    selector: 'my-app',\n    template: `\n        &lt;child-component #f [bar]=&quot;bar&quot;&gt;&lt;\/child-component&gt;&lt;br&gt;\n        &lt;button (click)=&quot;f.inc()&quot;&gt;call child func&lt;\/button&gt;\n        &lt;button (click)=&quot;bar = 'different'&quot;&gt;change parent var&lt;\/button&gt;\n    `,\n    directives: [ChildComponent]\n})\nclass AppComponent {\n    constructor () {\n        this.bar = 'parent var';\n    }\n}\n\nbootstrap(AppComponent);  <\/code><\/pre>\n<\/blockquote>\n<p>There is a working plunker for the above example <a href=\"http:\/\/plnkr.co\/edit\/F6S9r1nsLm11Q7TxxQoW?p=preview\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>With Angular, the component objects are automatically created and associated with their corresponding elements in the template. This raises the question then \u2013 if you want to refer to a child object from a parent component, how do you do it? There may be multiple child components of the same time in the parent component, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[198],"tags":[16,15],"_links":{"self":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2044"}],"collection":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2044"}],"version-history":[{"count":6,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2044\/revisions"}],"predecessor-version":[{"id":2050,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2044\/revisions\/2050"}],"wp:attachment":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2044"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2044"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2044"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}