Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 - How to clear an input with a local variable?

Following the guide from the Angular2 site I have this html:

<input #something (keyup)="doneTyping($event)">
<button (click)="add(something .value)">Add</button>

with this controller:

@Component({
  selector: 'my-app',
  appInjector: [SomeService]
})
@View({
  templateUrl: 'index-angular',
  directives:[NgFor]
})
class MyAppComponent {
  name: string;
  stuff: Array<string>;

  constructor(someService: SomeService) {
    this.name = 'Angular2Sample';
    this.stuff= someService.getStuff();
  }
  add(st: string){
    this.stuff.push(st);
  }
  doneTyping($event) {
    if($event.which === 13) {
      this.stuff.push($event.target.value);
      $event.target.value = null;
    }
  }
}

When the user hits enter in the input, the doneTyping method clears the input with $event.target.value = null;.

However I can't come with a way of doing the same after pushing the button.

like image 312
codependent Avatar asked Aug 05 '15 15:08

codependent


3 Answers

Also, you usually want to avoid interacting with DOM as much as possible. I just checked the Todo app example on the angular2 github and they also access the DOM element, but the last real commit is 2 months old.

If you use data binding you can have a cleaner code which would result in something like :

<input [value]="_newStuff" (keyup.enter)="addStuff()">
<button (click)="addStuff()">Add</button>

Then in your class you can just define the member _newStuff : string, that you can implement addStuff as follow :

addStuff() {
    this.stuff.push(_newStuff);
    this._newstuff = '';
}

In most cases you might want _newStuff to be a model object that works as an interface like this :

class Stuff {
    id : any;
    property : any;
    otherProperty : any;
}

And then your _newStuff would be _newStuff : Stuff; and you could map it like this : <input [value]="_newStuff.property" (keyup.enter)="addStuff()">.

I know your sample code is very simple and you just try to get it to work, but I believe the data binding way is more in the logic of the framework, and the Form API basically gives tools such as Control, ControlGroup and FormBuilder that help you map your model on your view with Validators and such. It would be too cumbersome on something a bit larger to access the DOM everytime you need to change the view. In the end your example is almost raw javascript executed in an Angular2 context.

Coming back to your example, now imagine you have another event that triggers a new stuff to be added, say a double click or so, you'd need to add another method that handles this event, passing it again the HTMLInputElement, and do basically the same thing as you do on the keyup event handler, thus duplicating code again. With data binding your component owns the state of the view and you can therefore have one simple method that won't be affected by what kind of event triggered it. There you can do the test if the model is valid ( even though for this you'd use the Form API then ).

Anyways, I know this has been answered already, but I thought I would just help to improve the solution given my current understanding of it and how it could be applied to real cases.

like image 76
Arnaud Boeglin Avatar answered Oct 27 '22 16:10

Arnaud Boeglin


You can pass the input as a parameter in the button

<input #something (keyup)="doneTyping($event)">

<!-- Input as paramter -->
<button (click)="add(something)">Add</button>

And later in the add function

add(st: HTMLInputElement){
    this.stuff.push(st.value);
    st.value = null;
  }
like image 27
Eric Martinez Avatar answered Oct 27 '22 15:10

Eric Martinez


You can use a one-direction bindings to access the value of the input. This is a very clear architecture; you don't have to pass DOM elements to the controller.

Template:

<!-- controller.value -> input.value binding-->
<input #myinput [value]=myValue>
<button (click)="done(myinput.value)">Add</button>

Controller:

myValue: string; // If you change this then the bound input.value will also change

// be sure to import ngOnInit from @angular/common
ngOnInit() {
    this.myValue = "";
}

done(newValue) {
    // ... processing newValue
    this.myValue = ""; // Clear the input
}
like image 27
Gábor Imre Avatar answered Oct 27 '22 17:10

Gábor Imre