#StackBounty: #javascript #forms #angular #control #onchange Angular 4 ControlValueAccessor value on submit and value changes events

Bounty: 100

Inside my Angular (4 + Typescript) project I used already prepared component (it doesn’t really matter which since the way of extending ControlValueAccessor is same, but if this matters I used ng2-select) which I wanted because of better UX and nicer look. After including it to my form component which is using reactive forms I saw, that on submit I get back (for the form control) object based on class SelectItem which is used inside prepared component, to manage selected item(s) – like this:

// console.log(this.myForm.values)
Object {
    txtInput: 'value',
    // ...
    preparedComponent: SelectItem { // <--
        id: '1',
        text: 'Chosen item'
    }
}

Since the component is basically just a replacement for standard select control, I was expecting that I’ll get back an ID of chosen item formed as string – like this:

// console.log(this.myForm.values)
Object {
    txtInput: 'value',
    // ...
    preparedComponent: '1' // <--
}

After I learned what actually ControlValueAccessor is and how it works, I changed the way of what comes back on submit (or better to say on item change – onChange) to the ID of an item. The problem was solved for some time until I started setting predefined values (on editing instance) to form controls instead of empty values (on adding instance). I figured out that this time the writeValue is assigning values to form control based on what it is sent to it as predefined value. So in case that I sent predefined value as …

Object {
    id: '1',
    text: 'Chosen item'
}

… this was also the value in Object on submit just as in the first code example above. I made a workaround for this, to assign correct value to control with onChange right after the writeValue is called. This was really improper way of doing it, but I couldn’t figured out anything other than that:

public writeValue(val: any): void {
    this.selectedItems = val; // val is for example Object { id: '1', text: 'Chosen item' }

    setTimeout(() => {
        this.onChange(val.id); // just an example of emitted value, there should be some checks val is object and id exists in real code
    }, 0);
}

And that also worked as far as I didn’t start with subscribe to form control’s valueChanges. The problem is that with each assigning of predefined value to prepared component, there is also an emit of the value used after submit, back to subscribers even when using { emitEvent: false }.

So this are the things I want to have handled with prepared component somehow, since I want to get right value from control on submit and I don’t want emit change to subscribers until the value is really not changed, not just replaced as predefined value. Any idea how to handle this will be appreciated.


Get this bounty!!!