Hesham Yassin
Hesham Yassin

Reputation: 4431

Angular 4 - How to get the index of $event.currTarget from the ViewContainerRef

What Am I trying to accomplish: When the user press enter inside a <p> element, a new <p> element is added right after it. it is possible that the user press the ENTER key on the 5th out o 70 views...

How Am i trying to do it: On the <p> element, there is a keyPress Listener. When the enter key is pressed, I am trying to get the index of the current element and add one right after as follows:

let dom_view = e.currentTarget
let index = this.richtextbox.indexOf(dom_view);

this.richtextbox.insert(this.p_dom.createEmbeddedView(null),index+1);

The issue i am facing: index is always -1 as e.currentTarget (same as e.target) is not identified by the container! What is the right way to get the index?

My Component code is:

import {
  AfterViewInit, Component, ViewChild, ViewContainerRef
} from '@angular/core';

@Component({
  selector: 'app-editor',
  templateUrl: './editor.component.html',
  styleUrls: ['./editor.component.css']

})
export class EditorComponent  implements AfterViewInit {

  @ViewChild('richtextbox', {read: ViewContainerRef}) richtextbox: ViewContainerRef;
  @ViewChild('p_dom') p_dom;

  ngAfterViewInit(): void {
    // insert a p element
    let view1 = this.p_dom.createEmbeddedView(null)
    this.richtextbox.insert(view1);
  }
  editor_keypress(e) {
    let dom_view = e.currentTarget

    if (e.key === 'Enter') {
      let index = this.richtextbox.indexOf(dom_view);
      // notice that index is the index of the view that the user pressed
      // the enter on. there can be 1000 views... and i want to add the new 
      // view right after the one that the user pressed the enter on
      console.log('index = ', index)

      this.richtextbox.insert(this.p_dom.createEmbeddedView(null),index+1);
    }
  }
}

The HTML context is:

<ng-container #richtextbox>
</ng-container>

<ng-template #p_dom>
  <p contenteditable="true" (keypress)="editor_keypress($event)">I am editable test message</p>
</ng-template>

Update

I ended up using Renderer2in order to manipulate the doms. The problem with the ViewRef is that i wasn't able to create Listenner with closure to the view as Described by Bougarfaoi's Answer. If you want to have a look at the code, here is a link to the github code.

Upvotes: 1

Views: 1054

Answers (1)

El houcine bougarfaoui
El houcine bougarfaoui

Reputation: 37393

the passed value in this.richtextbox.indexOf must be of type ViewRef and you're passing to it an HTMLElement so here is the solution :

Demo

import { AfterViewInit, Component, ViewChild, ViewContainerRef } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  @ViewChild('richtextbox', {read: ViewContainerRef}) richtextbox: ViewContainerRef;
  @ViewChild('p_dom') p_dom;
   view1
  ngAfterViewInit(): void {
    // insert a p element
    this.view1 = this.p_dom.createEmbeddedView(null)
    this.richtextbox.insert(this.view1);
  }
  editor_keypress(e) {
    let dom = e.currentTarget


    if (e.key === 'Enter') {
      let index = this.richtextbox.indexOf(this.view1);
      console.log(this.richtextbox);
      console.log('dom = ', dom)
      console.log('index = ', index)

      this.richtextbox.insert(this.p_dom.createEmbeddedView(null),index+1);
    }
  }
}

Upvotes: 1

Related Questions