1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Anuncie Aqui
    Anuncie aqui você Também: fdantas@4each.com.br

custom form input controValueAccessor cannot setup control

Discussão em 'Angular' iniciado por arpho, Setembro 14, 2024.

  1. arpho

    arpho Guest

    I want to implement a custom form input for my angular application, this is the component:

    import { CommonModule } from '@angular/common';
    import { Component, OnInit,Input, EventEmitter,Output, OnChanges, SimpleChanges, OnDestroy, ChangeDetectionStrategy, forwardRef } from '@angular/core';
    import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
    import { IonicModule, SearchbarCustomEvent } from '@ionic/angular';
    import { ValueAccessorDirective } from '../../directives/valueAccessor/value-accessor.directive';
    import { Subscription } from 'rxjs';
    import { CountryValue } from '../../models/countryValue';

    @Component({
    standalone:true,
    imports:[
    IonicModule,
    CommonModule,
    FormsModule,
    ReactiveFormsModule
    ],
    inputs:['data','multiple','itemTextField','value'],
    selector: 'app-searchable-select',
    templateUrl: './searchable-select.component.html',
    styleUrls: ['./searchable-select.component.scss'],
    hostDirectives:[ValueAccessorDirective],
    changeDetection:ChangeDetectionStrategy.OnPush,
    providers: [{
    provide: NG_VALUE_ACCESSOR,
    multi: true,
    useExisting: forwardRef(()=>SearchableSelectComponent)
    },]
    })
    export class SearchableSelectComponent implements OnInit,OnChanges,OnDestroy, ControlValueAccessor {
    isOpen = false
    @Input() value:CountryValue
    @Input() title = "Search"
    @Input() data:any[]
    @Input() multiple= false
    @Output() selectedChanged:EventEmitter<any> = new EventEmitter()
    @Input() itemTextField= 'name'
    disabled = false
    text =""
    touched = false
    selected =[]
    filtered =[]

    private onChange: Function = (country: CountryValue) => { };
    // tslint:disable-next-line: ban-types
    private onTouch: Function = () => { };
    subscription = new Subscription()

    constructor(
    private valueAccessor:ValueAccessorDirective<CountryValue[]>
    ){
    this.subscription.add( valueAccessor.value.subscribe((v)=>{
    console.log("subscription", v)
    }))
    }
    ngOnDestroy(): void {
    this.subscription.unsubscribe()
    }
    writeValue(obj: CountryValue): void {
    this.value = obj
    }



    registerOnChange(fn:any) {
    this.onChange = fn;
    }
    registerOnTouched(fn:any) {
    this.onTouch = fn;
    }



    setDisabledState?(isDisabled: boolean): void {
    isDisabled=isDisabled
    }
    ngOnChanges(changes: SimpleChanges): void {
    this.filtered = this.data
    }

    ngOnInit() {

    if(this.value){
    this.selected.push(this.value)
    }
    if( !this.multiple){
    this.data.forEach(d=>{d.selected = false})
    this.selectedChanged.emit([this.value])
    }
    }




    open(){
    this.isOpen=true
    }
    cancel(){
    this.isOpen= false
    }
    select(){
    this.isOpen= false
    }

    itemSelected(item){
    console.log("clicked",item )
    //remove not selected item
    this.selected = this.multiple? this.data.filter((item)=>item.selected):[item]
    this.valueAccessor.valueChange(this.selected)
    this.valueAccessor.touchedChange(true)
    this.valueAccessor.writeValue(this.selected)
    if(!this.multiple){ // we can select only one item
    this.data= this.data.map(d=>{
    if(d['key']!= item['key'])
    d['selected']= false
    return d
    })
    }
    this.selectedChanged.emit(this.selected)
    this.isOpen= false

    }

    filter(event:SearchbarCustomEvent){
    const filter = event.target.value.toLocaleLowerCase()
    this.filtered = this.data.filter(item=>{
    return this.leaf(item).toLocaleLowerCase().indexOf(filter)>=0
    })
    }


    leaf= (obj)=>obj[this.itemTextField]
    }


    for each control of my form a FormContol is instantiated and added to a FormGroup, after this I get an error on the Chrome's log:

    core.mjs:8400 ERROR TypeError: Cannot read properties of null (reading 'writeValue')
    at setUpControl (forms.mjs:2939:23)
    at FormGroupDirective.addControl (forms.mjs:4771:9)
    at FormControlName._setUpControl (forms.mjs:5321:43)
    at FormControlName.ngOnChanges (forms.mjs:5266:18)
    at FormControlName.rememberChangeHistoryAndInvokeOnChangesHook (core.mjs:1521:14)
    at callHook (core.mjs:2444:18)
    at callHooks (core.mjs:2403:17)
    at executeInitAndCheckHooks (core.mjs:2354:9)
    at selectIndexInternal (core.mjs:9059:17)
    at ɵɵadvance (core.mjs:9042:5)


    tell me if you need more details

    Continue reading...

Compartilhe esta Página