4 votes

Comment viewChild peut obtenir les éléments qui ont été ajoutés avec js dans angular2 ?

Si un élément HTML a été ajouté au DOM (par exemple après avoir cliqué sur un bouton), comment pouvons-nous accéder à cet élément ? viewChild ne peut pas le voir.

Mise à jour 1 : Plus de description

J'ai utilisé jquery datatable ( Version de jquery.dataTables definitelyTyped ). Sur la base de este je peux ajouter une nouvelle colonne et définir le html à l'intérieur de celle-ci. J'ai écrit ce code :

           columnDefs: [
                    {
                        render: function (data, type, row) {
                            return `
                                  <a href="admin/edituser/` + row.UserId+ `" class="btn btn-outline btn-circle btn-sm green"><i class="fa fa-edit" > </i> Edit </a>`+
                                 `<a [routerLink]="['Delete']" class="btn btn-outline btn-circle btn-sm red"><i class="fa fa-trash-o" > </i> Delete </a>
                                            `;
                        },
                        targets: 5
                    },
                ],

enter image description here

Avec les outils pour développeurs de Chrome, je vois ceci : enter image description here

La première balise d'ancrage fonctionne mais avec href, pas routerLink.

La deuxième balise d'ancrage ne fonctionne pas parce que les directives angulaires ne sont pas conformes à href.

J'ai essayé d'utiliser DynamicComponentLoader pour le compiler, et j'ai modifié le code comme ceci : enter image description here

Mais je ne peux pas accéder à l'élément #target avec viewChild (je veux le remplacer par un autre composant par loadNextToLocation). Je pense que ce n'est pas la meilleure façon d'obtenir un bon résultat.

Je veux utiliser un routerLink avec des boutons de commande dans une table de données jquery.

Pouvez-vous m'aider à résoudre ce problème ?

Merci d'avance.

solution :

Si vous voulez ajouter du HTML au DOM avec du javascript ou une fonction de rappel, déterminez d'abord une balise à partir du modèle qui peut être un parent pour ces éléments à l'avenir.

  1. Ajoute une variable de modèle à cet élément parent (#target par exemple).

                    <th> Email</th>
                    <th> Date </th>
                    <th> Phone </th>
                    <th> Commands</th>
    
                </tr>
            </thead>
            <tbody #target></tbody>
            <tfoot>
                <tr>
    
                    <th>  </th>
                    <th>  </th>
                    <th>  </th>
                    <th>  </th>
    
                </tr>
            </tfoot>
        </table>
  2. Ensuite, ajoutez une classe simple et un attribut simple à votre code html (ce code est généré après la compilation de la page avec Angular, vous pouvez également écrire du code avec typescript ou javascript pour générer du html).

       columnDefs: [
                    {
                        render: function (data, type, row) {
                            return `
                                 `<a date-id="` + row.UserId + `" class="editbtn btn btn-outline btn-circle btn-sm red"> Edit</a>
                                 `;
                        },
                        targets: 5
                    },
                ],
  3. Maintenant, importez et injectez ces sources dans votre composant :

        import {ViewChild, Renderer} from '@angular/core';

    et :

        constructor(private renderer: Renderer, private router: Router)
  4. Définissez une variable viewChild dans votre classe de composant :

        @ViewChild('target') target;
  5. Écrivez une fonction comme celle-ci :

    public AfterEverything() {
           var el: HTMLElement = this.target.nativeElement;//Make an Element Object
           console.log(el);
           var commands: NodeListOf<Element> = el.getElementsByClassName('editbtn');//Find Element Object to get all elements with a specefic class
           console.log(commands);
           for (var i = 0; i < commands.length; i++) {
               //Loop for add event or style
               console.log(commands[i]);
               //Sample event(Click for routing)
               this.renderer.listen(commands[i], 'click', (event: Event) => {
                   var thisid = event.srcElement.getAttribute("date-id");//Get value from element
                   console.log(thisid);
                   this.router.parent.navigate(['EditUser', { id: thisid }]);//Use value to make routeLink
                   console.log(event.srcElement.innerHTML);
               });
               this.renderer.setElementStyle(commands[i], 'backgroundColor', 'yellow');//for change color(just sample)
           }

    }

  6. Vous devez trouver le meilleur endroit pour appeler cette fonction, par exemple, le callback des données ajax est un choix et appeler AfterEverything() à l'intérieur de celui-ci. Vous pouvez appeler cette fonction à l'intérieur de ngAfterViewInit().

Notez que parfois un délai de plusieurs secondes est nécessaire pour s'assurer que tous les nouveaux éléments sont créés.

1voto

Günter Zöchbauer Points 21340

Si vous ajoutez du HTML de manière dynamique (comme [innerHTML]="someHtml" ), vous pouvez alors utiliser un accès direct au DOM (mal vu dans Angular2) en injectant ElementRef et en utilisant ElementRef.nativeElement.querySelector...

Si le HTML est généré en utilisant *ngFor vous pouvez ajouter des variables de modèle et demander ces éléments comme suit

<div *ngFor="let x of y" #someVar></div>

et ensuite dans la classe du composant

@ViewChildren('someVar') elements;

ngAfterViewInit() {
  console.log(this.elements);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X