viewchild form and emitting on change

1,856 views
Skip to first unread message

Jonathan Price

unread,
May 17, 2017, 7:34:33 PM5/17/17
to Angular and AngularJS discussion
I can't get this work work.  Tried the setTimeout and detectChanges suggestions to no avail.

Sander Elias

unread,
May 17, 2017, 10:53:49 PM5/17/17
to Angular and AngularJS discussion
Hi Jonathan,

You can't use the afterview* lifecycle hooks to make any changes that affect your view's data. Do that in the ngOnInit, or any of the other places. 
I assume you have a 3rth party that changes something in your data when it initialises? Try listening to the event it triggers, and hook into that. On an input you would do something like:

<input ... (changes)="fireValidEvent()">

I'm pretty sure, your problem can be solved that way.

Regards
Sander

Jonathan Price

unread,
May 18, 2017, 12:07:01 PM5/18/17
to Angular and AngularJS discussion
Yes, I already have (changes) on all the inputs.  The problem is I need the initial form state to emit once all of the values are populated.  This isn't the case within ngOnInit.  When I check form.valid in ngOnInit, I'm definitely seeing the wrong state.  If I console.log in afterview, I see it get updated to the correct state.

Jonathan Price

unread,
May 18, 2017, 3:49:08 PM5/18/17
to Angular and AngularJS discussion
Sorry, I updated the plunker to better reflect my problem!


It stems from an async subscription to the form data source and the need to update the form validity accordingly.  Thanks!


On Wednesday, May 17, 2017 at 7:53:49 PM UTC-7, Sander Elias wrote:

Jonathan Price

unread,
May 18, 2017, 5:23:05 PM5/18/17
to Angular and AngularJS discussion

Sander Elias

unread,
May 18, 2017, 11:20:50 PM5/18/17
to Angular and AngularJS discussion
Hi Jonathan,

Looks good. Altough, it can be a bit simpler, have a look at this:

@Component({
  selector
: 'form-child',
 
template: `
    <div>
      <form #campaignForm="ngForm">
        <input type="text" [ngModel]='data.input' name='input' required/>
      </form>
    </div>
  `
,
})
export class FormChild implements OnInit, AfterViewInit, AfterViewChange {
 
@Output() valid = new EventEmitter();
 
@ViewChild('campaignForm') campaignForm: NgForm;

  constructor
() {}
 
  ngOnInit
() {
   
this.campaignForm.valueChanges.subscribe(data => {
     
this.valid.emit(this.campaignForm.form.valid);
   
}
 
}  
}


Will work just as well, and you can get rid of some extra constructs.

Regards
Sander

Sander Elias

unread,
May 18, 2017, 11:24:46 PM5/18/17
to Angular and AngularJS discussion
Hi Jonathan,

Just realised, you don't need a template var to get the form, this will work also, and your template gets cleaner:

@Component({
  selector
: 'form-child',
 
template:
`
    <div>
      <form>

        <input type="text" [ngModel]='data.input' name='input' required/>
      </form>
    </div>
  `
,

})
export class FormChild implements OnInit, AfterViewInit, AfterViewChange {

 
@Input() data: any;

 
@Output() valid = new EventEmitter();

 
@ViewChild(NgForm) campaignForm: NgForm;


  constructor
() { }
 
  ngOnInit
() {
   
this.campaignForm.valueChanges.subscribe(data => {
     
this.valid.emit(this.campaignForm.form.valid);
   
}
 
}  
}

Regards
Sander
Reply all
Reply to author
Forward
0 new messages