Denny Rustandi
Denny Rustandi

Reputation: 347

bind reactive form formControlName in ng2-select2 directive

I'm using Reactive Form for handling form in my Angular 5 project. And in that form I'm using ng2-select2 to create my select2 dropdown, but when I'm trying to bind formControlName into my <select2></select2> directive, it gives me error

ERROR Error: No value accessor for form control with name: 'citizenship_id'

Here is my ngOnInit function in .ts file:

ngOnInit() {
    this.jobId = this.route.snapshot.queryParams.jobId;
    this.detailForm = new FormGroup({
        date_of_birth: new FormControl(null, Validators.required),
        gender: new FormControl('', Validators.required),
        marital_status: new FormControl('', Validators.required),
        npwp_family_status_id: new FormControl('', Validators.required),
        citizenship_id: new FormControl('', Validators.required),
    });

    this.ajaxOptions = {
        url: API_URL + '/generate-json',
        dataType: 'json',
        delay: 250,
        data: function (params) {
            return {
                s: params.term,
                page: params.page,
                model_name: 'country'
            };
        },
        type: 'POST',
        processResults: function (res) {
            let data = $.map(res.results, function (obj) {
                if (obj.overwriteId)
                    obj.id = obj.overwriteId;
                return obj;
            });

            return {
                results: data,
                pagination: res.pagination
            };
        }
    };

    this.options = {
        ajax: this.ajaxOptions,
        // theme: 'bootstrap',
        width: '100%',
        allowClear: true,
        placeholder: 'Select...',
        language: {
            'errorLoading': function () {
                return 'Searching…';
            }
        },
        templateResult: function (data) {
            return data.create === true ? data.text + ' <b style="color: lightgreen;">(create new)</b>' : data.text;
        },
        templateSelection: function (data) {
            return data.create === true ? data.text + ' <b class="text-success">(create new)</b>' : data.text;
        },
        escapeMarkup: function (markup) {
            return markup;
        },
        createTag: function (params) {
            var term = $.trim(params.term);
            return term ? {
                id: term,
                text: term,
                create: true
            } : null;
        },
        insertTag: function (data, tag) {
            var found = false;
            $.each(data, function (i, e) {
                if (e.text.toLowerCase() == tag.text.toLowerCase())
                    found = true;
            });
            if (!found)
                data.unshift(tag);
        },
        minimumInputLength: 2
    };
}

And this is my .html file:

<select2 [options]="options" formControlName="citizenship_id"></select2>

Upvotes: 2

Views: 2878

Answers (2)

Jeremy Moritz
Jeremy Moritz

Reputation: 14912

While Select2 doesn't work with ReactiveForms natively, here's a good workaround solution:

Create a new hidden input bound to formControlName. Whenever value of select2 is changed, update the value of the hidden input as well.

If you get the response from API and you want to pre-select the value, Use an array variable with selected value from the response (e.g.: [{id: 1, text: 'Selected Value'}] then in select2 directive, set [value]="{selected_value_id}").

Credit to OP @DennyRustandi and @SunilSingh for this info in the comments.

Upvotes: 1

Sunil
Sunil

Reputation: 11243

Issue is with your custom component select2. It seems your component is not implementing ControlValueAccessor. Just ensure your component does implement ControlValueAccessor.

See the simple example - https://stackblitz.com/edit/angular-custom-from-control-hqpwgb

Refer this nice article - https://alligator.io/angular/custom-form-control/

Upvotes: 1

Related Questions