Skip to content

Commit 43d7dc3

Browse files
committed
fix(core): find schemas correctly
1 parent c0e0ffc commit 43d7dc3

File tree

6 files changed

+57
-38
lines changed

6 files changed

+57
-38
lines changed

packages/core/src/lib/directives/render/form.directive.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import { FluentFormRenderModule } from './module';
1515
<div [fluentSchema]="schema()" [(fluentModel)]="model" (fluentFormChange)="form = $event">
1616
<fluent-outlet key="ipt" />
1717
<fluent-outlet key="ipts" />
18-
<fluent-outlet key="group.ipt" />
19-
<fluent-outlet key="group.ipts" />
18+
<fluent-outlet [key]="['group', 'ipt']" />
19+
<fluent-outlet [key]="['group', 'ipts']" />
2020
<fluent-outlet key="array" />
2121
</div>
2222
`

packages/core/src/lib/directives/render/outlet.directive.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { computed, Directive, effect, inject, input, ViewContainerRef } from '@angular/core';
22
import { AbstractControl } from '@angular/forms';
33
import type { AnyArray, AnyObject } from '@ngify/core';
4-
import type { AbstractSchema, SingleSchemaKey } from '../../schemas';
4+
import type { AbstractSchema, SchemaKey, SingleSchemaKey } from '../../schemas';
55
import { WidgetTemplateRegistry } from '../../services';
66
import { SchemaUtil } from '../../utils';
77
import type { WidgetTemplateContext } from '../../widgets';
@@ -22,14 +22,19 @@ export class FluentOutletDirective<T extends AnyObject | AnyArray> implements Wi
2222

2323
private readonly _control = computed(() => {
2424
const form = this.controlContainer.form();
25-
return form.get(this.key().toString()) ?? form;
25+
const paths = this.schemaUtil.norimalizePaths(this.key());
26+
return form.get(paths) ?? form;
2627
});
2728

2829
private readonly _model = computed(() => {
2930
const rootModel = this.controlContainer.model();
30-
const paths = this.schemaUtil.parsePathKey(this.key().toString());
31+
const paths = this.schemaUtil.norimalizePaths(this.key());
3132
// Delete the last key to get the parent model
32-
return paths.slice(0, -1).reduce((obj, key) => obj?.[key as keyof T] as T, rootModel);
33+
return paths
34+
.map(path => this.schemaUtil.parsePathKey(path))
35+
.flat()
36+
.slice(0, -1)
37+
.reduce((obj, key) => obj?.[key as keyof T] as T, rootModel);
3338
});
3439

3540
get control(): AbstractControl {
@@ -44,7 +49,7 @@ export class FluentOutletDirective<T extends AnyObject | AnyArray> implements Wi
4449
return this._model();
4550
}
4651

47-
readonly key = input.required<SingleSchemaKey>();
52+
readonly key = input.required<SingleSchemaKey | SchemaKey[]>();
4853

4954
constructor() {
5055
effect(() => {

packages/core/src/lib/testing/components/range/range.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, forwardRef } from '@angular/core';
2-
import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
2+
import { type ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
33

44
@Component({
55
selector: 'fluent-range',

packages/core/src/lib/utils/schema.utils.spec.ts

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -170,17 +170,6 @@ describe('SchemaUtil', () => {
170170
expect(schemaUtil.find(schema(), 'name')).toEqual({ kind: 'text-field', key: 'name' });
171171
});
172172

173-
it('二级图示', () => {
174-
const schema = form(() => {
175-
group('group').schemas(() => {
176-
textField('name');
177-
});
178-
});
179-
180-
expect(schemaUtil.find(schema(), ['group', 'name'])).toEqual({ kind: 'text-field', key: 'name' });
181-
expect(schemaUtil.find(schema(), 'group.name')).toEqual({ kind: 'text-field', key: 'name' });
182-
});
183-
184173
it('多级图示', () => {
185174
const schema = form(() => {
186175
group('group').schemas(() => {
@@ -191,16 +180,23 @@ describe('SchemaUtil', () => {
191180
});
192181

193182
expect(schemaUtil.find(schema(), ['group', 'group', 'name'])).toEqual({ kind: 'text-field', key: 'name' });
194-
expect(schemaUtil.find(schema(), 'group.group.name')).toEqual({ kind: 'text-field', key: 'name' });
195183
});
196184

197-
it('多字段图示', () => {
185+
it('multi key schema', () => {
198186
const schema = form(() => {
199187
range(['begin', 'end']);
200188
});
201189

202190
expect(schemaUtil.find(schema(), [['begin', 'end']])).toEqual({ kind: 'range', key: ['begin', 'end'] });
203-
expect(schemaUtil.find(schema(), ['begin', 'end'].toString())).toEqual({ kind: 'range', key: ['begin', 'end'] });
191+
expect(schemaUtil.find(schema(), 'begin,end')).toEqual({ kind: 'range', key: ['begin', 'end'] });
192+
});
193+
194+
it('object path key schema', () => {
195+
const schema = form(() => {
196+
textField('name.first');
197+
});
198+
199+
expect(schemaUtil.find(schema(), 'name.first')).toEqual({ kind: 'text-field', key: 'name.first' });
204200
});
205201

206202
it('不存在的图示', () => {
@@ -215,11 +211,31 @@ describe('SchemaUtil', () => {
215211
range(['begin', 'end']);
216212
});
217213

218-
expect(schemaUtil.find(schema(), null!)).toBe(null);
219214
expect(schemaUtil.find(schema(), [['begin', 'e']])).toBe(null);
220215
expect(schemaUtil.find(schema(), ['begin', 'e'].toString())).toBe(null);
221216
});
222217
});
218+
219+
describe('norimalizePaths', () => {
220+
it('should normalize a single string key', () => {
221+
expect(schemaUtil.norimalizePaths('name')).toEqual(['name']);
222+
expect(schemaUtil.norimalizePaths(1)).toEqual(['1']);
223+
});
224+
225+
it('should normalize a object path key', () => {
226+
expect(schemaUtil.norimalizePaths('a.b')).toEqual(['a.b']);
227+
});
228+
229+
it('should normalize a paths', () => {
230+
expect(schemaUtil.norimalizePaths(['a', 'b'])).toEqual(['a', 'b']);
231+
expect(schemaUtil.norimalizePaths([1, 2])).toEqual(['1', '2']);
232+
expect(schemaUtil.norimalizePaths(['a', 1])).toEqual(['a', '1']);
233+
});
234+
235+
it('should normalize an array with a nested array key', () => {
236+
expect(schemaUtil.norimalizePaths([['a', 'b'], 'c', 1])).toEqual(['a,b', 'c', '1']);
237+
});
238+
});
223239
});
224240

225241
describe('SchemaUtil with patcher feature', () => {

packages/core/src/lib/utils/schema.utils.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -152,26 +152,24 @@ export class SchemaUtil {
152152
return key.split('.');
153153
}
154154

155+
norimalizePaths(paths: SingleSchemaKey | SchemaKey[]) {
156+
return (isArray(paths) ? paths : [paths]).map(o => o.toString());
157+
}
158+
155159
find(schema: Indexable<AbstractBranchSchema>, key: SingleSchemaKey): AbstractSchema | null;
156160
find(schema: Indexable<AbstractBranchSchema>, key: SchemaKey[]): AbstractSchema | null;
157-
find(schema: Indexable<AbstractBranchSchema>, path: SingleSchemaKey | SchemaKey[]): AbstractSchema | null;
158-
find(schema: Indexable<AbstractBranchSchema>, path?: SingleSchemaKey | SchemaKey[]): AbstractSchema | null {
159-
if (!path) return null;
160-
161-
const paths = isArray(path)
162-
? path.map(o => isArray(o) ? o.toString() : o)
163-
: path.toString().split('.');
164-
165-
let _schema: Indexable<AbstractSchema> | null = schema;
161+
find(schema: Indexable<AbstractBranchSchema>, paths: SingleSchemaKey | SchemaKey[]): AbstractSchema | null;
162+
find(schema: Indexable<AbstractBranchSchema>, paths: SingleSchemaKey | SchemaKey[]): AbstractSchema | null {
163+
let currentSchema: Indexable<AbstractSchema> | null = schema;
166164

167-
for (const path of paths) {
168-
_schema = _schema['schemas'].find((o: AbstractSchema) => o.key?.toString() === path) ?? null;
165+
for (const path of this.norimalizePaths(paths)) {
166+
currentSchema = currentSchema['schemas'].find((o: AbstractSchema) => o.key?.toString() === path) ?? null;
169167

170-
if (_schema === null) {
171-
return _schema;
168+
if (currentSchema === null) {
169+
return currentSchema;
172170
}
173171
}
174172

175-
return _schema;
173+
return currentSchema;
176174
}
177175
}

packages/docs/src/app/pages/advanced/customization/examples/custom-layout/custom-layout.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<fluent-outlet key="age" />
1818
</td>
1919
<td>
20-
<fluent-outlet key="info.birthday" />
20+
<fluent-outlet [key]="['info', 'birthday']" />
2121
</td>
2222
<td>
2323
<fluent-outlet key="enabled" />

0 commit comments

Comments
 (0)