Angular 2 ControlValueAccessor for custom checkbox, How inside to outside value get updated? -
i trying implement custom component checkbox using bootstrap 4 checkbox layout.
i following link implement custom component http://almerosteyn.com/2016/04/linkup-custom-control-to-ngcontrol-ngmodel
i did radio, checkbox taking input array of ids , output array of ids based on selection.
checkbox created based on list of js model instance.
export class inputprop<t>{ displayname?:string; order?:number; constructor( public checked:boolean=false, public value:string, public id:t) {}
}
but 1 thing not understanding, how angular 2 read inner value , update outside modal
there writevalue method read outside component ngmodel values.
is there method readvalue
source code
checkbox-button.component.ts import { inputprop } './../../models/common.classes'; import { titlecasepipe } './../../../pipes/title-case.pipe'; import { formgroup, formcontrol, formbuilder, controlvalueaccessor, ng_value_accessor, ng_validators, validatorfn } '@angular/forms'; // framework import { input, output, component, oninit, ondestroy, forwardref, eventemitter } "@angular/core"; const noop = () => { }; export const custom_input_control_value_accessor: = { provide: ng_value_accessor, useexisting: forwardref(() => checkboxbutton), multi: true }; @component({ selector: 'checkbox-button', styleurls:['./../buttons.component.scss'], templateurl:'./checkbox-button.component.html', providers:[titlecasepipe] }) export class checkboxbutton implements oninit, ondestroy, controlvalueaccessor { private titlecase:titlecasepipe=new titlecasepipe(); //(ngmodelchange)="cbacheckboxbuttonchange($event)" @input('label') private labelname:string; @input('list') private complist:inputprop<number|string>[]; @input('isenum') private isenumbasecheckbox:boolean=false; @input('enumlist') private enumcomp:any; @input('isupcase') private isuppercase:boolean=false; @input('sortdir') private sortdir:string='asc'; @input('labeldir') private islabeldisplaydir:string='top'; @output() oncheckboxchangenotify: eventemitter<(number|string)[]>; private prevselectedvals:(number|string)[]; private innerval: any[]; private orderby:any; constructor() { this.oncheckboxchangenotify = new eventemitter<(number|string)[]>(); } ngoninit() { this.orderby={fields:['order'],sortdir:this.sortdir}; //console.debug('cbacheckboxbutton::ngoninit: ',this.complist,this.labelname); } ngondestroy(){ //console.debug('cbacheckboxbutton::ngondestory: '); } //placeholders callbacks later providesd //by control value accessor private ontouchedcallback: () => void = noop; private onchangecallback: (_: any) => void = noop; //get accessor selectedval(): { return this.innerval; }; // //set accessor including call onchange callback // set selectedval(v: any) { // if (v !== this.innerval) { // this.innerval = v; // this.onchangecallback(v); // } // } //from controlvalueaccessor interface writevalue(value: any) { if (value !== this.innerval) { this.innerval = value; this.complist.map(f=>f.checked=false); for(let val in this.innerval) this.complist.filter(f=>f.id==val).map(f=>f.checked=true); // initialize checkbox select or deseclt based on input } } //set touched on blur onblur() { this.ontouchedcallback(); } //from controlvalueaccessor interface registeronchange(fn: any) { this.onchangecallback = fn; } //from controlvalueaccessor interface registerontouched(fn: any) { this.ontouchedcallback = fn; } changecheckbox(checkbox:inputprop<number>,event:boolean):boolean { console.debug('cbacheckboxbutton::changecheckbox: ',checkbox,event); // below code deselect other if or global selected if(checkbox.id!=-1){ this.complist.filter(f => f.checked && f.id==-1 ).map(f=>f.checked=false); } else { this.complist.filter(f => f.checked && f.id!=-1 ).map(f=>f.checked=false); } this.innerval=this.complist.filter(f => f.checked).map(f=>(f.id));; this.ontouchedcallback(); // let selectedinputs=this.complist.filter(f => f.checked).map(f=>(f.id)); // let me=this; // if(selectedinputs.length==0){ // this.complist.map(f=>{ // if(f.id==me.prevselectedvals[0]) // f.checked=true; // }); // return true; // } // // there small bug here, when try deselect last record, prevented these code , works perfet // // when jump others , try deselect again tried, need twice click // this.prevselectedvals=selectedinputs; return false; // this.updateparentlistener(); } // updateparentlistener():boolean { // this.oncheckboxchangenotify.emit(selectedinputs); // } }
checkbox-button.component.html <div class="btn-group d-flex flex-default" *ngif="islabeldisplaydir=='left' || islabeldisplaydir=='right'"> <label class="btn btn-primary radio-label labelname btn-right-border" *ngif="islabeldisplaydir=='left'">{{labelname}}</label> <template [ngif]="!isenumbasecheckbox"> <label class="btn btn-primary radio-label btn-right-border" [ngclass]="{'radio-label-checked':checkbox.checked}" *ngfor="let checkbox of complist | orderby:orderby" > <input type="checkbox" class="radio-input" (blur)="onblur()" [value]="checkbox.checked" [(ngmodel)]="checkbox.checked" (ngmodelchange)="changecheckbox(checkbox,$event)"> {{ isuppercase ? (checkbox.displayname||checkbox.value | uppercase):(checkbox.displayname||checkbox.value | titlecase)}} </label> </template> <label class="btn btn-primary radio-label labelname btn-right-border" *ngif="islabeldisplaydir=='right'">{{labelname}}</label> </div> <div *ngif="islabeldisplaydir=='top' || islabeldisplaydir=='bottom'"> <div class="btn-group d-flex flex-default" *ngif="islabeldisplaydir=='top'"> <label class="btn btn-primary radio-label labelnametb">{{labelname}}</label><br/> </div> <div class="btn-group d-flex flex-default"> <template [ngif]="!isenumbasecheckbox"> <label class="btn btn-primary radio-label btn-right-border" [ngclass]="{'radio-label-checked':checkbox.checked}" *ngfor="let checkbox of complist | orderby:orderby" > <input type="checkbox" class="radio-input" (blur)="onblur()" [value]="checkbox.checked" [(ngmodel)]="checkbox.checked" (ngmodelchange)="changecheckbox(checkbox,$event)"> {{ isuppercase ? (checkbox.displayname||checkbox.value | uppercase):(checkbox.displayname||checkbox.value | titlecase)}} </label> </template> </div> <div class="btn-group d-flex flex-default" *ngif="islabeldisplaydir=='bottom'"> <label class="btn btn-primary radio-label labelnametb">{{labelname}}</label><br/> </div> </div>
Comments
Post a Comment