Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Three way binding in Angular 2 and Angularfire2

I am trying to three-way bind an input element to firebase database in Angular.js 2 (2.0.0-rc.4), using AngularFire 2 (2.0.0-beta.2).

I have a very simple html like:

<form (ngSubmit)="onSubmit()" #commentForm="ngForm">
  <input [(ngModel)]="model.author" type="input" name="author" required>
</form>

In my component, to save and retrieve contents of this input to firebase, I have an implementation like this:

export class CommentFormComponent implements OnInit, AfterViewInit {
  @ViewChild("commentForm") form;
  // http://stackoverflow.com/questions/34615425/how-to-watch-for-form-changes-in-angular-2

  firebaseInitComplete = false;
  model: Comment = new Comment("", "");
  firebaseForm: FirebaseObjectObservable<Comment>;

  constructor(private af: AngularFire) { }

  ngAfterViewInit() {
    this.form.control.valueChanges
      .subscribe(values => {
        // If we haven't get the initial value from firebase yet,
        // values will be empty strings. And we don't want to overwrite
        // real firebase value with empty string on page load
        if (!this.firebaseInitComplete) { return; }

        // If this is a change after page load (getting initial firebase value) update it on firebase to enable 3-way binding
        this.firebaseForm.update(values);
      });
  }

  ngOnInit() {
    this.firebaseForm = this.af.database.object("/currentComment");
    // Listen to changes on server
    this.firebaseForm.subscribe(data => {
      this.firebaseInitComplete = true; // Mark first data retrieved from server
      this.model = data;
    });
  }    
}

The code above works, I am able to read initial firebase value and update value on firebase when user type something in real time.

But having a manual logic to check for this.firebaseInitComplete and adding ngAfterViewInit to listen for changes feels a little bit wrong and I am just hacking it to work.

Is there a better implementation of three-way binding with less logic inside component?

like image 428
Umut Benzer Avatar asked Jul 22 '16 08:07

Umut Benzer


People also ask

What is 2 way data binding in Angular?

The two-way data binding in Angular is used to display information to the end user and allows the end user to make changes to the underlying data using the UI. This makes a two-way connection between the view (the template) and the component class. This is similar to the two-way binding in WPF.

What's the difference between one-way and two-way data binding in Angular?

Difference between One-way & Two-way BindingIn one-way binding, the flow is one-directional. In a two-way binding, the flow is two-directional. This means that the flow of code is from ts file to Html file. This means that the flow of code is from ts file to Html file as well as from Html file to ts file.

What are the types of binding in Angular?

AngularJS provides two types of Data Binding: One-way data binding. Two-way data binding.

Can't bind to [( ngModel )] since it is not provided by any applicable directives?

To fix Can't bind to 'ngModel' since it isn't a known property of 'input' error in Angular applications we have to import FormModule in app. module. ts file. If you are using FormBuilder class to create reactive form we have to import ReactiveFormsModule as well to avoid below error.


1 Answers

Seven months later and I have an answer for you.. extended ngModel syntax..

<input [ngModel]='(model|async)?.author' (ngModelChange)="model.update({author: $event})">

The [] block is a getter and the () block is a setter. Since the model's getter is actually unwrapping the FirebaseObjectObservable, you have to use the FirebaseObjectObservable's binding to set it.

like image 132
Jon Thompson Avatar answered Oct 12 '22 23:10

Jon Thompson