Skip to content

Commit

Permalink
fix(Select): Provide an optional fix directive for <novo-select> elem…
Browse files Browse the repository at this point in the history
…ents (#1560)

* fix(Select): Provide an optional fix directive for <novo-select> elements that adjusts checkboxes after a value update

* fix(QueryBuilder): Missing label on isNull operator
  • Loading branch information
davidkbh authored Jun 28, 2024
1 parent 0208003 commit 0684b27
Show file tree
Hide file tree
Showing 8 changed files with 33,995 additions and 33,523 deletions.
67,405 changes: 33,887 additions & 33,518 deletions projects/demo/assets/documentation.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';
import { AbstractConditionFieldDef } from './abstract-condition.definition';
import { Operator } from '../query-builder.types';
import { NovoSelectElement } from 'novo-elements/elements/select';

/**
* Handle selection of field values when a list of options is provided.
Expand All @@ -19,7 +20,7 @@ import { Operator } from '../query-builder.types';
</novo-field>
<ng-container *novoConditionInputDef="let formGroup; fieldMeta as meta" [ngSwitch]="formGroup.value.operator" [formGroup]="formGroup">
<novo-field *novoSwitchCases="['includeAny', 'includeAll', 'excludeAny']">
<novo-select formControlName="value" [placeholder]="labels.select" [multiple]="true">
<novo-select extupdatefix formControlName="value" [placeholder]="labels.select" [multiple]="true">
<!-- WHat about optionUrl/optionType -->
<novo-option *ngFor="let option of meta?.options" [value]="option.value" [attr.data-automation-value]="option.label">
{{ option.label }}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// NG
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
// App
import { NovoSelectElement } from './Select';
import { NovoSelectModule } from './Select.module';
import { NovoLabelService } from 'novo-elements/services';
import { NovoOptionModule } from 'novo-elements/elements/common';
import { Component, ViewChild } from '@angular/core';
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';

@Component({
template: `
<form [formGroup]="form">
<novo-select #select extupdatefix formControlName="value" multiple>
<novo-option value="1">One</novo-option>
<novo-option value="2">Two</novo-option>
<novo-option value="3">Three</novo-option>
</novo-select>
</form>`
})
class FixedSelectComponent {
@ViewChild('select')
select: NovoSelectElement;

form = new FormGroup({
value: new FormControl(['2'])
});
}

describe('Directive: NovoSelectExtUpdateFix', () => {
let fixture: ComponentFixture<FixedSelectComponent>;
let comp: FixedSelectComponent;

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [NovoSelectModule, NovoOptionModule, FormsModule, ReactiveFormsModule],
providers: [NovoLabelService],
declarations: [FixedSelectComponent],
}).compileComponents();
fixture = TestBed.createComponent(FixedSelectComponent);
comp = fixture.debugElement.componentInstance;
fixture.detectChanges();
}));

it('should update checkboxes when the ngmodel value is updated externally', () => {
expect(comp.select.contentOptions.map(opt => opt.selected)).toEqual([false, true, false]);
comp.form.controls.value.setValue(['1']);
expect(comp.select.contentOptions.map(opt => opt.selected)).toEqual([true, false, false]);
});

// This case may arise if, for instance, a dynamic form is about to transform this
// control from a novo-select to something else.
it('should not trigger errors from negative use-case variables', () => {
(comp.form.controls.value as FormControl).setValue('candy');
})
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Directive, OnInit, inject } from '@angular/core';
import { FormControl, NgControl } from '@angular/forms';
import { NovoSelectElement } from './Select';

/**
* Fixes a <novo-select> element so that if its value is updated externally, the checkboxes in the dropdown selector
* update accordingly. Because this is a functionality change to a core control, this fix is provided as a directive
* to only be used if needed.
*/
@Directive({
selector: 'novo-select[extupdatefix]'
})
export class NovoSelectExtUpdateFix implements OnInit {
control = inject(NgControl);
selectElement = inject(NovoSelectElement);

ngOnInit() {
if (this.control?.control && 'registerOnChange' in this.control.control) {
(this.control.control as FormControl).registerOnChange((rawValue, viewToModelUpdate) => {
if (this.selectElement.multiple === Array.isArray(rawValue)) {
this.afterExternalUpdate(rawValue);
}
});
}
}

afterExternalUpdate(rawValue: any) {
this.selectElement['_setSelectionByValue'](rawValue);
}
}
5 changes: 3 additions & 2 deletions projects/novo-elements/src/elements/select/Select.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { NovoOptionModule, NovoOverlayModule } from 'novo-elements/elements/comm
import { NovoDividerModule } from 'novo-elements/elements/divider';
import { NovoTooltipModule } from 'novo-elements/elements/tooltip';
import { NovoSelectElement } from './Select';
import { NovoSelectExtUpdateFix } from './Select.extupdatefix.directive';

@NgModule({
imports: [
Expand All @@ -23,7 +24,7 @@ import { NovoSelectElement } from './Select';
NovoPipesModule,
NovoTooltipModule,
],
declarations: [NovoSelectElement],
exports: [NovoSelectElement],
declarations: [NovoSelectElement, NovoSelectExtUpdateFix],
exports: [NovoSelectElement, NovoSelectExtUpdateFix],
})
export class NovoSelectModule {}
1 change: 1 addition & 0 deletions projects/novo-elements/src/elements/select/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './Select';
export * from './Select.module';
export * from './Select.extupdatefix.directive';
1 change: 1 addition & 0 deletions projects/novo-elements/src/services/novo-label-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ export class NovoLabelService {
after = 'After';
between = 'Between';
within = 'Within';
isNull = 'Is Empty';
isEmpty = 'Is Empty?';
refreshPagination = 'Refresh Pagination';
location = 'Location';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,20 @@ export const MockMeta = {
multiValue: true,
inputType: 'SELECT',
optionsType: 'BusinessSector',
optionsUrl: '/options/BusinessSector',
options: [
{
value: 'Agriculture',
label: 'Agriculture',
},
{
value: 'Nursing',
label: 'Nursing',
},
{
value: 'Finance',
label: 'Finance',
},
],
hideFromSearch: false,
sortOrder: 760,
hint: '',
Expand Down

0 comments on commit 0684b27

Please sign in to comment.