0

I have the following javascript and html that allows me to click a button to edit text, how do I make it so that it works with angular2 if there are multiple buttons?

<button>Button Text Could Be Editable</button><br />
<button (click)="modifyText()" data-edit="0">Edit Button Above</button>

<script>
function modifyText() {
this.previousElementSibling.previousElementSibling.contentEditable = !!(+(this.dataset.edit = this.dataset.edit == 0 ? 1 : 0))
}
</script>

In angular2, I have a list of students in my scope that I want to be rendered on a button, but I can "Edit" their name on the button only if I click on the specific button.

// this is part of the component
this.students = ['John', 'Jacob', 'Patty'];

// this is the html in my template for the component
<button *ngFor="name of students" (click) = "modifyText()">{{name}}</button><br />

How do I modify modifyText() function within the component so that in angular2, I can get a reference to the specific button and make it editable just like in my non-angular example for a single button?

Am looking for a response using the latest version of Angular as I know this has changed a couple of times.

Rolando
  • 58,640
  • 98
  • 266
  • 407

1 Answers1

0

You can get a reference to the HTML element that was clicked by using the $event object. Most of the guides tell you to use the target property of the event object but I like to use currentTarget because:

It always refers to the element to which the event handler has been attached, as opposed to event.target which identifies the element on which the event occurred.

This guarantees that I will get the correct reference to the HTML element that I am listening for the click on. In the template pass in the current HTML element as a parameter like so:

<button *ngFor="name of students"
        (click)="modifyText($event.currentTarget)">{{name}}</button>

and then recieve it in the component like so:

public modifyText(htmlElement: HTMLElement) {
    this.dataset.edit = !this.dataset.edit;
    htmlElement.contentEditable = this.dataset.edit;
    htmlElement.focus();
}
Teddy Sterne
  • 13,774
  • 2
  • 46
  • 51
  • This is working-ish, but I've noticed that as soon as the button is "contentEditable", I lose focus (i dont see i cursor unless i click on the button again). Is there a way to force htmlElement to "focus" with showing the text cursor? (That way I can start typing immediately) – Rolando Apr 28 '17 at 19:09
  • Thank you. I was getting confused with all the posts I saw like http://stackoverflow.com/questions/38944725/how-to-get-dom-element-in-angular-2 with ElementRef and all that. – Rolando Apr 28 '17 at 19:16
  • Gotcha. For reference ElementRef is typically injected into the constructor to get a reference to the component's html tag/DomElement – Teddy Sterne Apr 28 '17 at 19:19
  • Thanks. I noticed that when I use contenteditable like that, I lose the binding to {{name}}, say if I wanted a separate button that excplicitly modified the name in the scope. Do you know if tehre is a way to preserve that binding? – Rolando Apr 28 '17 at 19:30
  • You might be able to preserve that using an [(ngModel)], you could also probably bind using `(blur)="name = $event.target.value"` and it would probably update the name value for you. – Teddy Sterne Apr 28 '17 at 23:58