Why is Angular not showing the values of a string[] -


i've created plunker here - https://plnkr.co/edit/1aztv5k2gqic4erngrng?p=preview

tl;dr to see problem should open developer tools window , @ console log output. go <input> box , repeatedly add text , clear it. see value of errors output console, errors never appear in component's view.

i've written custom component implements ng_value_accessor give control databinding context, , ng_validators can have access data source (abstractcontrol) being validated.

i cannot see why *ngfor in component's template not listing errors can see present looking in console.log output.

import {component, ngmodule, forwardref} '@angular/core' import {browsermodule} '@angular/platform-browser' import { reactiveformsmodule, formsmodule } '@angular/forms'; import { formgroup, formbuilder, validators } '@angular/forms'; import {   abstractcontrol, controlvalueaccessor, ng_validators, ng_value_accessor, validationerrors,   validator } '@angular/forms'; import { observable } 'rxjs/observable'; import { behaviorsubject } 'rxjs/behaviorsubject'; import 'rxjs/add/operator/distinctuntilchanged';  @component({   selector: 'validation-errors',   template: `     <div>errors should appear below line</div>     <div *ngfor='let item of errors'>{{ item }}!!!</div>     `,   providers: [     {       provide: ng_validators,       useclass: forwardref(() => validationerrorscomponent),       multi: true     },     {       provide: ng_value_accessor,       useclass: forwardref(() => validationerrorscomponent),       multi: true     }   ] }) export class validationerrorscomponent implements validator, controlvalueaccessor  {   public errors: string[] = [];    private control: abstractcontrol = null;    private updateerrors(errorsobject: any) {     this.errors = [];     if (errorsobject) {       (const errortype of object.keys(errorsobject)) {         this.errors.push(errortype);       }     }     console.log('errors: ' + json.stringify(this.errors));   }    validate(c: abstractcontrol): validationerrors | {     if (this.control === null && c !== null && c !== undefined) {       this.control = c;       this.control.statuschanges         .distinctuntilchanged()         .subscribe(x => this.updateerrors(this.control.errors));     }   }    writevalue(obj: any): void {   }    registeronchange(fn: any): void {   }    registerontouched(fn: any): void {   }  } 

it doesn't seem change detection problem, have tried implementing using observables , async pipe , still shows no errors.

the consumer code looks this

//our root app component import {component, ngmodule, forwardref} '@angular/core' import {browsermodule} '@angular/platform-browser' import { reactiveformsmodule, formsmodule } '@angular/forms'; import { formgroup, formbuilder, validators } '@angular/forms'; import {   abstractcontrol, controlvalueaccessor, ng_validators, ng_value_accessor, validationerrors,   validator } '@angular/forms'; import { validationerrorscomponent } './validation-errors.component';  @component({   selector: 'my-app',   template: `     <div [formgroup]='form'>       <input formcontrolname='name' style="width: 100%"/>        <validation-errors formcontrolname='name'></validation-errors>     </div>   `, }) export class app {   public form: formgroup;    constructor(formbuilder: formbuilder) {     this.form = formbuilder.group({       name: ['delete text trigger required vaidation error', validators.required]     })   } }  @ngmodule({   imports: [ browsermodule, formsmodule, reactiveformsmodule ],   exports: [         formsmodule,     reactiveformsmodule,     validationerrorscomponent   ],   declarations: [ app, validationerrorscomponent ],   bootstrap: [ app ] }) export class appmodule {} 

update: problem 3 instances of component being created. 1 markup in template, 1 ng_validators provider, , 1 ng_value_accessor provider. because had specified useclass instead of useexisting in provider declarations. use original code, think directive nicer implement adding <input> can share formcontrolname.

i have reverted old code consists of directive creates instance of validator. wishes achieve same goal here source. note create instances of validationerror, simple class.

/**  * used denote validation error of kind  *  * @class validationerror  */ export class validationerror {   /**    * @constructor    * @param (string) message key translation of text display    * @param parameters additional parameters (max-length, etc)    */   constructor(public message: string, public parameters: any) {} } 

here source directive:

import { componentfactoryresolver, directive, forwardref, ondestroy, oninit, viewcontainerref } '@angular/core'; import { abstractcontrol, ng_validators, validationerrors, validator } '@angular/forms'; import { observable } 'rxjs/observable'; import { behaviorsubject } 'rxjs/behaviorsubject'; import { validationerror } '../../validation-error'; import { validationerrorscomponent } '../../components/validation-errors/validation-errors.component';  @directive({   selector:     '[formcontrol][showvalidationerrors], ' +     '[formcontrolname][showvalidationerrors], ' +     '[ngmodel][showvalidationerrors]',   providers: [     {       provide: ng_validators,       useexisting: forwardref(() => showvalidationerrorsdirective), multi: true     }   ] }) export class showvalidationerrorsdirective implements validator, oninit, ondestroy  {   errors: observable<validationerror[]>;    private issubscribedtocontrol = false;   private isdestroyed = false;   private validationerrorscomponent: validationerrorscomponent;   private errorssubject: behaviorsubject<validationerror[]>;    constructor(     private viewcontainerref: viewcontainerref,     private componentfactoryresolver: componentfactoryresolver   ) {     this.errorssubject = new behaviorsubject([]);     this.errors = observable.from(this.errorssubject);   }    ngoninit() {     const factory = this.componentfactoryresolver.resolvecomponentfactory(validationerrorscomponent);     const componentreference = this.viewcontainerref.createcomponent(factory);     this.validationerrorscomponent = componentreference.instance;     this.validationerrorscomponent.errors = this.errors;   }    validate(control: abstractcontrol): validationerrors | {     this.subscribetocontrolerrors(control);     return null; // haven't added errors   }    private subscribetocontrolerrors(control: abstractcontrol) {     if (!this.issubscribedtocontrol) {       this.issubscribedtocontrol = true;       control.statuschanges         .takewhile(x => !this.isdestroyed)         .distinctuntilchanged()         .map(x => control.errors)         .subscribe(x => this.populateerrors(x));     }   }    private populateerrors(errorsobject: any) {     const errors = [];     if (errorsobject) {       (const errortype of object.keys(errorsobject)) {         errors.push(new validationerror(errortype, errorsobject[errortype]));       }     }     this.errorssubject.next(errors);   }    registeronvalidatorchange(fn: () => void): void {   }     ngondestroy(): void {     this.isdestroyed = true;   } } 

here template component:

<div *ngfor="let error of errors | async">   {{ error.message | translate }} </div> 

and source component:

import { component, input } '@angular/core'; import { validationerror } '../../validation-error'; import { observable } 'rxjs/observable';  @component({   selector: 'validation-errors',   templateurl: './validation-errors.component.html',   styleurls: ['./validation-errors.component.scss'], }) export class validationerrorscomponent  {   @input()   errors: observable<validationerror[]>; } 

and finally, how used in consumer:

<input formcontrolname="mobilenumber" showvalidationerrors /> 

Comments

Popular posts from this blog

PHP and MySQL WP -

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

go - golang pprof for c library code -