0

How can I use ViewChild in Angular 2 Javascript? I have referred angular.io docs and I have tried with the following code and it is not working. Can anyone help me? Thanks in advance.

main.html

<router-outlet></router-outlet>

app.component.js

(function (app) {

app.AppComponent = ng.core
        .Component({
            selector: 'my-app',
            templateUrl: 'app/views/main.html',
            directives: [ng.router.ROUTER_DIRECTIVES], //<----not loading components here
            viewProviders: [ng.http.HTTP_PROVIDERS],
            queries: {
                'viewChild1Component': new ng.core.ViewChild(app.Child1Component) //Parent calls Child 1 using ViewChild
            },
        })
        .Class({
            constructor: [ng.router.Router, ng.http.Http, function (router, http) {
                this.router = router;
                this.http = http;

            }],
            ngAfterViewInit: function () {
                this.viewChild1Component.onSubmit();
            },
        });

ng.router
        .RouteConfig([
          //loading components here
          { path: '/child1', component: app.Child1Component, name: 'Child 1', useAsDefault: true }, 
        ])(app.AppComponent);

})(window.app || (window.app = {}));

child1.js

(function (app) {

    app.Child1Component = ng.core
            .Component({
                selector: 'test',
                template: '<div>Test</div>',
            })
            .Class({
                constructor: [ng.router.Router, function (router) {
                    this.router = router;
                }],
                onSubmit: function () {
                    alert('Call from Parent');
                },
            });

})(window.app || (window.app = {}));

index.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <!-- 1. Load libraries -->
    <script src="scripts/traceur-runtime.js"></script>
    <script src="scripts/system.js"></script>
    <!-- IE required polyfill -->
    <script src="scripts/es6-shim.min.js"></script>

    <script src="scripts/angular2-polyfills.js"></script>
    <script src="scripts/Rx.umd.js"></script>
    <script src="scripts/angular2-all.umd.js"></script>

    <!--components-->
    <script src="app/components/child1.js"></script>
    <script src="app/components/child2.js"></script>

    <!-- 2. Load our 'modules' -->
    <script src='app/app.component.js'></script>
    <script src='app/boot.js'></script>

</head>
<!-- 3. Display the application -->
<body>
    <my-app>Loading...</my-app>
</body>
</html>
Abraham Gnanasingh
  • 837
  • 2
  • 10
  • 31

1 Answers1

2

You need to define your field into the queries attribute of your component metadata, as described below:

var AppComponent = ng.core.
  Component({
    selector: "app", 
    template:
      '<div>' +
      '  <test></test>' +
      '</div>',
    queries: {
      'subComponent': new ng.core.ViewChild(TestComponent) <-----
    },
    directives: [ TestComponent ]
  })
  .Class({
    constructor: function() {
    },

    ngAfterViewInit:function(){
      this.subComponent.onSubmit();
    }
  });

The subComponent will set before the ngAfterViewInit hook is called.

The previous code relies on the following TestComponent:

var TestComponent = ng.core.Component({
    selector:'test',
    template: '<div>Test</div>'
  }).Class({
    constructor: function(){
    },

    onSubmit: function(){
      console.log('onSubmit');
    }
  });

Edit

In your case, you leverage routing. This means that your viewChild1Component property will be set after the call of the ngAfterViewInit method since the Child1Component component is loaded in the router-outlet after. Things are dynamic in fact...

If you use the viewChild1Component property after (on a click for example), this will work... See the sample below:

app.AppComponent = ng.core.
  Component({
    selector: "app", 
    template:
     '<div>' +
     '  <router-outlet></router-outlet>' +
     '  <div (click)="submit()">Submit</div>' +
     '</div>',
  queries: { 'viewChild1Component': new ng.core.ViewChild(Child1Component) },
  directives: [ng.router.ROUTER_DIRECTIVES]
})
.Class({
  submit: function() {
    console.log('#### submit');
    this.viewChild1Component.onSubmit();
  }
});
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • It's you again! Thanks and Love. I have tried your code and is working 100% fine. I understood your code and found the problem existing in my application is that I have used **Routing**. I don't load the component in template. I load the component in `` using `ng.router.RouteConfig`. Therfore I can't view the child in `ngAfterViewInit` – Abraham Gnanasingh Mar 08 '16 at 06:29
  • You're welcome! Regarding your last question, you try to reference a component loaded in `router-outlet` from the component that uses `router-outlet`. Right? – Thierry Templier Mar 08 '16 at 08:44
  • Yep. I don't load component in **directives**. I load component using **ng.router.RouteConfig**. I have edited this question. Please check it. You will get an idea of what I have done. – Abraham Gnanasingh Mar 08 '16 at 09:05
  • Okay, I see know. In fact, the sub component is loaded in `router-outlet` after the call of the `ngAfterViewInit` method. So the `viewChild1Component` property should be used later (on a click) for example. I updated my answer... – Thierry Templier Mar 08 '16 at 09:57
  • Working fine now. Thanks a lot. And I need 1 more help from you. I wanna know how to use **CanActivate** in Javascript. [My Post regarding CanActivate](http://stackoverflow.com/questions/35794034/prevent-default-routing-angular-2). This is the link I have posted on. Please check this and help me to solve the problem – Abraham Gnanasingh Mar 08 '16 at 10:53
  • Thanking you again and again is not enough I think. My best wishes to you in everything – Abraham Gnanasingh Mar 08 '16 at 10:57
  • Is there an option to listen after the `router-outlet` component has been loaded? – Abraham Gnanasingh Mar 08 '16 at 13:30
  • You can leverage component lifecycle hooks (something like ngAfterViewInit). What do you want to do exactly? – Thierry Templier Mar 08 '16 at 13:32
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/105697/discussion-between-abraham-a-and-thierry-templier). – Abraham Gnanasingh Mar 08 '16 at 13:33
  • Since I have used router-outlet, and you told that I can use `ViewChild` after the call of the `ngAfterViewInit` method. That is why I am asking like, Is there an option to listen after the `router-outlet`'s component has been loaded? – Abraham Gnanasingh Mar 08 '16 at 13:42
  • I can't add ViewChild queries in angular 2 rc version Can you help me to solve this issue? Can you give a correct code for this? – Abraham Gnanasingh May 15 '16 at 16:06
  • Can you look out my new question in the [link](http://stackoverflow.com/questions/37287510/viewchild-not-working-in-angular-2-rc-1-javascript) and solve my issue? – Abraham Gnanasingh May 20 '16 at 16:32
  • Will I use on behalf of EventEmitter? Or EventEmitter is a different concept? Because I am new to Angular 2 so... @ThierryTemplier – Jignesh Vagh Jun 29 '17 at 07:44