Skip to content

Commit 6c43e41

Browse files
Merge pull request #677 from bigopon/fix-hierarchical-select
fix(SelectValueObserver): observe characterData mutation
2 parents 9b103d9 + e982ae0 commit 6c43e41

File tree

2 files changed

+101
-12
lines changed

2 files changed

+101
-12
lines changed

src/select-value-observer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ export class SelectValueObserver {
155155
this.synchronizeOptions();
156156
this.synchronizeValue();
157157
});
158-
this.domObserver.observe(this.element, { childList: true, subtree: true });
158+
this.domObserver.observe(this.element, { childList: true, subtree: true, characterData: true });
159159
}
160160

161161
unbind() {

test/select-value-observer.spec.js

Lines changed: 100 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
import './setup';
2-
import {DOM} from 'aurelia-pal';
3-
import {bindingMode} from '../src/binding-mode';
4-
import {
5-
createElement,
6-
checkDelay,
7-
createObserverLocator,
8-
getBinding
9-
} from './shared';
10-
import {createScopeForTest} from '../src/scope';
2+
import { DOM } from 'aurelia-pal';
3+
import { bindingMode } from '../src/binding-mode';
4+
import { createElement, checkDelay, createObserverLocator, getBinding } from './shared';
5+
import { createScopeForTest } from '../src/scope';
116

127
describe('SelectValueObserver', () => {
138
var observerLocator;
@@ -16,10 +11,10 @@ describe('SelectValueObserver', () => {
1611
observerLocator = createObserverLocator();
1712
});
1813

19-
function getElementValue(element) {
14+
function getElementValue (element) {
2015
var options = element.options, option, i, ii, count = 0, value = [];
2116

22-
for(i = 0, ii = options.length; i < ii; i++) {
17+
for (i = 0, ii = options.length; i < ii; i++) {
2318
option = options.item(i);
2419
if (!option.selected) {
2520
continue;
@@ -671,4 +666,98 @@ describe('SelectValueObserver', () => {
671666
document.body.removeChild(el);
672667
});
673668
});
669+
670+
describe('hierarchical select', () => {
671+
var obj;
672+
/**@type {HTMLSelectElement} */
673+
var select1;
674+
/**@type {HTMLSelectElement} */
675+
var select2;
676+
var binding1;
677+
var binding2;
678+
679+
beforeEach(() => {
680+
class Car {
681+
constructor (name, models, selectedModelIndex) {
682+
this.name = name;
683+
this.models = models;
684+
this.selectedModelIndex = selectedModelIndex;
685+
this.selectedModel = this.models[selectedModelIndex];
686+
}
687+
}
688+
689+
let cars = [
690+
new Car('Audi', ['Child11', 'Child12', 'Child13'], 2),
691+
new Car('BMW', ['Child21', 'Child22', 'Child23'], 1),
692+
new Car('Buick', ['Child31', 'Child32', 'Child33'], 2)
693+
];
694+
obj = {
695+
cars: cars,
696+
selectedCar: cars[2]
697+
};
698+
select1 = createElement(
699+
`<select>
700+
<option>Audi</option>
701+
<option>BMW</option>
702+
<option>Buick</option>
703+
</select>`
704+
);
705+
select2 = createElement(
706+
`<select>
707+
<option>Child31</option>
708+
<option>Child32</option>
709+
<option>Child33</option>
710+
</select>`
711+
);
712+
document.body.appendChild(select1);
713+
document.body.appendChild(select2);
714+
715+
for (let i = 0; i < select1.options.length; ++i) {
716+
observerLocator.getObserver(select1.options[i], 'model').setValue(cars[i]);
717+
}
718+
binding1 = getBinding(observerLocator, obj, 'selectedCar', select1, 'value', bindingMode.twoWay).binding;
719+
binding2 = getBinding(observerLocator, obj, 'selectedCar.selectedModel', select2, 'value', bindingMode.twoWay).binding;
720+
// binding2 = getBinding(observerLocator, obj, 'optionB', select1.options.item(1), 'value', bindingMode.toView).binding
721+
});
722+
723+
it('binds', done => {
724+
var targetObserver = observerLocator.getObserver(select1, 'value');
725+
binding1.bind(createScopeForTest(obj));
726+
expect(select1.options.item(2).selected).toBe(true);
727+
binding2.bind(createScopeForTest(obj));
728+
setTimeout(() => {
729+
expect(select2.value).toBe('Child33');
730+
done();
731+
}, 80);
732+
});
733+
734+
it('changes child select value correctly', done => {
735+
var targetObserver = observerLocator.getObserver(select1, 'value');
736+
binding1.bind(createScopeForTest(obj));
737+
expect(select1.options.item(2).selected).toBe(true);
738+
binding2.bind(createScopeForTest(obj));
739+
obj.selectedCar.selectedModel = obj.selectedCar.models[1];
740+
setTimeout(() => {
741+
expect(select2.value).toBe('Child32');
742+
obj.selectedCar = obj.cars[1];
743+
setTimeout(() => {
744+
expect(select1.options.item(1).selected).toBe(true);
745+
for (let i = 0, ii = select2.options.length; ii > i; ++i) {
746+
select2.options[i].textContent = obj.selectedCar.models[i];
747+
}
748+
setTimeout(() => {
749+
expect(select2.options.item(1).selected).toBe(true);
750+
done();
751+
}, 80);
752+
}, 80);
753+
}, 80);
754+
});
755+
756+
afterEach(() => {
757+
binding1.unbind();
758+
binding2.unbind();
759+
document.body.removeChild(select1);
760+
document.body.removeChild(select2);
761+
});
762+
});
674763
});

0 commit comments

Comments
 (0)