diff --git a/packages/angular/cli/models/schematic-command.ts b/packages/angular/cli/models/schematic-command.ts index 5b7c03259b..ded5925dfa 100644 --- a/packages/angular/cli/models/schematic-command.ts +++ b/packages/angular/cli/models/schematic-command.ts @@ -309,7 +309,7 @@ export abstract class SchematicCommand< question.type = 'confirm'; break; case 'list': - question.type = 'list'; + question.type = !!definition.multiselect ? 'checkbox' : 'list'; question.choices = definition.items && definition.items.map(item => { if (typeof item == 'string') { return item; diff --git a/packages/angular_devkit/core/src/json/schema/interface.ts b/packages/angular_devkit/core/src/json/schema/interface.ts index 9861a30889..4269b191a1 100644 --- a/packages/angular_devkit/core/src/json/schema/interface.ts +++ b/packages/angular_devkit/core/src/json/schema/interface.ts @@ -99,13 +99,14 @@ export interface PromptDefinition { id: string; type: string; message: string; - default?: string | number | boolean | null; + default?: string | string[] | number | boolean | null; priority: number; validator?: (value: string) => boolean | string | Promise; items?: Array; raw?: string | JsonObject; + multiselect?: boolean; } export type PromptProvider = (definitions: Array) diff --git a/packages/angular_devkit/core/src/json/schema/prompt_spec.ts b/packages/angular_devkit/core/src/json/schema/prompt_spec.ts index d1bb23c12f..6e74e7fb65 100644 --- a/packages/angular_devkit/core/src/json/schema/prompt_spec.ts +++ b/packages/angular_devkit/core/src/json/schema/prompt_spec.ts @@ -262,6 +262,83 @@ describe('Prompt Provider', () => { .toPromise().then(done, done.fail); }); + it('analyzes list with multiselect option and object items', done => { + const registry = new CoreSchemaRegistry(); + const data: any = {}; + + registry.usePromptProvider(async definitions => { + expect(definitions.length).toBe(1); + expect(definitions[0].type).toBe('list'); + expect(definitions[0].multiselect).toBe(true); + expect(definitions[0].items).toEqual([ + { 'value': 'one', 'label': 'one' }, + { 'value': 'two', 'label': 'two' }, + ]); + + return { [definitions[0].id]: { 'value': 'one', 'label': 'one' } }; + }); + + registry + .compile({ + properties: { + test: { + type: 'array', + 'x-prompt': { + 'type': 'list', + 'multiselect': true, + 'items': [ + { 'value': 'one', 'label': 'one' }, + { 'value': 'two', 'label': 'two' }, + ], + 'message': 'test-message', + }, + }, + }, + }) + .pipe( + mergeMap(validator => validator(data)), + ) + .toPromise().then(done, done.fail); + }); + + it('analyzes list without multiselect option and object items', done => { + const registry = new CoreSchemaRegistry(); + const data: any = {}; + + registry.usePromptProvider(async definitions => { + expect(definitions.length).toBe(1); + expect(definitions[0].type).toBe('list'); + expect(definitions[0].multiselect).toBeUndefined(); + expect(definitions[0].items).toEqual([ + { 'value': 'one', 'label': 'one' }, + { 'value': 'two', 'label': 'two' }, + ]); + + return { [definitions[0].id]: { 'value': 'two', 'label': 'two' } }; + }); + + registry + .compile({ + properties: { + test: { + type: 'array', + 'x-prompt': { + 'type': 'list', + 'items': [ + { 'value': 'one', 'label': 'one' }, + { 'value': 'two', 'label': 'two' }, + ], + 'message': 'test-message', + }, + }, + }, + }) + .pipe( + mergeMap(validator => validator(data)), + ) + .toPromise().then(done, done.fail); + }); + it('analyzes enums WITHOUT explicit list type', done => { const registry = new CoreSchemaRegistry(); const data: any = {}; diff --git a/packages/angular_devkit/core/src/json/schema/registry.ts b/packages/angular_devkit/core/src/json/schema/registry.ts index 71a4b7a6ce..b228a0896f 100644 --- a/packages/angular_devkit/core/src/json/schema/registry.ts +++ b/packages/angular_devkit/core/src/json/schema/registry.ts @@ -568,6 +568,7 @@ export class CoreSchemaRegistry implements SchemaRegistry { priority: 0, raw: schema, items, + multiselect: type === 'list' ? schema.multiselect : false, default: typeof parentSchema.default == 'object' ? undefined : parentSchema.default, async validator(data: string) { const result = it.self.validate(parentSchema, data); diff --git a/packages/angular_devkit/schematics_cli/bin/schematics.ts b/packages/angular_devkit/schematics_cli/bin/schematics.ts index b5e97bb3c0..3ce98f7fa1 100644 --- a/packages/angular_devkit/schematics_cli/bin/schematics.ts +++ b/packages/angular_devkit/schematics_cli/bin/schematics.ts @@ -98,7 +98,7 @@ function _createPromptProvider(): schema.PromptProvider { case 'list': return { ...question, - type: 'list', + type: !!definition.multiselect ? 'checkbox' : 'list', choices: definition.items && definition.items.map(item => { if (typeof item == 'string') { return item;