j-p
j-p

Reputation: 3828

ng-select CSS issues, bootstrap input-sm

So while using ng-select on a reactive form, I'm trying to style the field on error (invalid) like this.

the field:

<ng-select class="form-control input-sm" [class.store-error]="showError('store')"...

The show error method looks like this - and works for ALL OTHER FORM FIELDS

showError (fieldName: string) {
    const field = this.form.get(fieldName);
    return field.invalid && (field.touched || this.submitAttempted);
}

ng select does not change classes.

It appears as though ng-select constructs a div on top of a form field element, and changing the bootstrap class to input-sm exposes this (so a secondary question is how to get the input-sm applied to ng-select)

enter image description here

this CSS isse is secondary to the field NOT showing invalid using css-binding. Has anyone solved this?

enter image description here

You can see here that the containing div is taking the css, but ng-selects generated div is not...so the annomoly of applying the input-sm style, revealed a bug - as the ng-select doesn't inherit the style

Upvotes: 2

Views: 13307

Answers (3)

alindber
alindber

Reputation: 188

This issue has been frustrating. I have a Angular 7 Reactive form using 'BootStrap v4' including validation messages. When I crated select or multi-select form elements using 'ng-select', the styling was not consistent... UGH. By using Andzej Maciusovic answer above solved my issue.

Here is how my reactive template looks that uses ng-select:

<div
    class="dynamic=field form-input row"
    [formGroup]="group"
>
    <label
        [for]="configData[elementName]"
        class="col-5 my-form-label control-label"
    >
        {{displayField}}
    </label>
    <div class="col-7 ">
        <ng-select
            [id]="configData[elementName]"
            [formControlName]="configData[elementName]"
            class="form-control"
            [ngClass]="((!group.get(configData[elementName]).touched && 
                         group.get(configData[elementName]).pristine) ?
                             'border border-primary' :
                             (group.get(configData[elementName]).errors && 
                              group.get(configData[elementName]).touched) ? 
                                  'is-invalid' : 'is-valid')"
        >
            <ng-option
                *ngFor="let sName of selectData[optionKey];"
                [value]="sName[optionKey]">{{sName[optionDisplay]}}
             </ng-option>
        </ng-select>
        <ng-container *ngFor="let validation of configData[validation];">
            <div class="invalid-feedback"
                *ngIf="group.get(configData[elementName]).hasError(validation.valName.toLocaleLowerCase())
                       && (group.touched || group.valid) ">
                {{validation.valMessage}}
            </div>
        </ng-container>
    </div>
</div>

Note: the scope values elementName, optionKey, optionDisplay and validation are object names in configData that holds all of the field formatting information.

My code is based of a blog post by Todd Moto called Configurable Reactive Forms in Angular with dynamic components. Recommended.

Upvotes: 0

j-p
j-p

Reputation: 3828

because of the way ng-select generates a DOM element I needed to add a class to handle the reference.

This is the class used in site,

.state-error {
    background-color: #ffcccc;
    border-color: #ff0000;
}

This is the class I needed to add for the ng-select.

.ng-select.state-error .ng-control {
    background-color: #ffcccc;
    border-color: #ff0000;
}

All other things being equal on the validation front - this worked for me.

Upvotes: 0

Andzej Maciusovic
Andzej Maciusovic

Reputation: 4476

1) Here is plunker example showing applied custom error class https://plnkr.co/edit/zF6GsJ?p=preview

2) Bootstrap .form-control class is mostly used for native html elements, but custom elements which already has some styling will not work correctly so you need to style them yourself.

.form-control.ng-select {
    border: none;
    padding: 0;
}

Upvotes: 8

Related Questions