In an Angular CLI workspace, how do you make every `ng generate component` default to SCSS and no spec file, and which setting wins?
answer
- angular.json, not a wrapper script
- a schematics block keyed collection:schematic
- global, workspace, then project
- command-line flags beat all config
- cli.schematicCollections picks the collection
basics
~10 sAdd "@schematics/angular:component": { "style": "scss", "skipTests": true } under a schematics block in angular.json. Project-level entries override workspace-level ones, which override global ones, and a flag typed on the command line overrides them all.
solid answer
~40 sGenerator defaults live in `angular.json` under a `schematics` key, mapping `<collection>:<schematic>` to option values, for example `"@schematics/angular:component": { "style": "scss", "skipTests": true }`. The block can sit at the top level for the whole workspace or inside `projects.<name>` for one project, and `ng config` can write it for you. The CLI merges global config (by default `~/.angular-config.json`), then the workspace block, then the project block, so the most specific wins. Options typed on the command line are applied last and beat every stored default. Which collection a bare name like `component` comes from is a separate setting: `cli.schematicCollections`. Its first collection that defines the name wins, and `@schematics/angular` is used when it is unset.
code
bash · 4 linesng config schematics.@schematics/angular:component.style scss
ng config schematics.@schematics/angular:component.skipTests true
ng g c banner # scss, no spec
ng g c banner --skip-tests=false # command line wins: spec is writtengo deeper
Know that ng generate defaults can be stored in angular.json so you stop repeating flags.
Explain the collection:schematic key, the global-workspace-project-command-line precedence, and use ng config to write it.
Diagnose why a default is ignored, and route bare names to a team collection with cli.schematicCollections without breaking the built-in generators.
Decide which conventions belong in committed generator defaults versus lint rules, so new code is correct by construction across many projects.
## Where generator defaults live Every option of a schematic comes from its `schema.json`, and each option has a built-in default: for the component schematic `style` is `css` and `skipTests` is `false`. A team rarely wants those. Rather than asking everyone to remember `--style scss --skip-tests`, the CLI lets the workspace store its own defaults in `angular.json` under a key named `schematics`. The key maps a **schematic name** in the form `<collection>:<schematic>` to an object of option values: ```json { "schematics": { "@schematics/angular:component": { "style": "scss", "skipTests": true }, "@schematics/angular:service": { "skipTests": true } }, "projects": { "admin": { "schematics": { "@schematics/angular:component": { "prefix": "adm", "inlineStyle": true } } } } } ``` The option names are the schema's property names in camelCase (`skipTests`, `inlineStyle`, `changeDetection`), not the dashed flag spelling. The CLI also accepts a nested form, `"@schematics/angular": { "component": { ... } }`, and merges it after the qualified form. ## The merge order When `ng generate` runs, the CLI builds the option set in this order. Each later step overwrites keys set by an earlier one: 1. **The schematic's own schema defaults**, the fallback for anything not set elsewhere. 2. **Global CLI config**, the user-level file written by `ng config --global` (by default `~/.angular-config.json`). 3. **The workspace `schematics` block** at the top level of `angular.json`. 4. **The project's `schematics` block**, for the project you target with `--project` or the one the current directory belongs to. 5. **Options typed on the command line**, which always win. With the example above, `ng g c banner --project admin` produces SCSS (workspace), no spec (workspace), the `adm` prefix and inline styles (project). `ng g c banner --project admin --skip-tests=false` still writes a spec file, because the typed flag is applied last. | Level | Where | Typical use | |---|---|---| | Global | `~/.angular-config.json` | A developer's personal taste; avoid for team rules | | Workspace | top-level `schematics` in `angular.json` | Team-wide conventions, committed with the repo | | Project | `projects.<name>.schematics` | A library's prefix, or an app that inlines styles | | Command line | flags on `ng generate` | One-off exceptions | ## Writing it without hand-editing JSON `ng config` reads and writes `angular.json` paths, so a team can script the setup: - `ng config schematics.@schematics/angular:component.style scss` - `ng config projects.admin.schematics.@schematics/angular:component.prefix adm` The CLI writes such blocks itself too. `ng new --standalone false` stores `standalone: false` for the component, directive and pipe schematics. A workspace created with the 2016 file-name style stores `type` and `typeSeparator` defaults, so later generations keep the `.component.ts` naming. ## Choosing the collection: `cli.schematicCollections` The defaults above say *how* a schematic runs. A separate setting says *which* schematic a bare name means. `cli.schematicCollections` is a list of collection package names, set at workspace or project level (under the `cli` key) or globally. For a bare name such as `component`, the CLI walks the list in order and uses the **first collection that defines that name**. When the list is unset it falls back to `@schematics/angular`. That matters when a team or a third-party library ships its own `component` generator: - `["@my-org/schematics", "@schematics/angular"]` makes `ng g c` use the team's generator. Every name the team collection lacks (`service`, `pipe`) still resolves from `@schematics/angular`. - Leaving `@schematics/angular` out of the list means names only it defines no longer resolve by their short form, unless the team collection `extends` it. - A fully qualified name such as `ng g @schematics/angular:component x` always bypasses the list. ## Checking what actually applied The quickest way to see the merged result is to run the generator with `--dry-run`. With the defaults above, `ng g c banner --dry-run` should list a `.scss` file and no `.spec.ts`. If it does not, one of the levels is overriding another. Run the command from the project folder you expect, or pass `--project`, because the project-level block is chosen by the project the CLI resolves. In a multi-project workspace, a library project typically carries its own `prefix` default so its selectors differ from the application's. ## Common mistakes - Putting dashed flag names (`"skip-tests"`) in the JSON instead of schema property names. - Expecting a default to override a flag typed on the command line; the command line always wins. - Setting team conventions in the global file, so they silently differ between machines and CI. - Confusing the `schematics` block (option defaults) with `cli.schematicCollections` (name resolution).
- A developer says their `ng g c` ignores the workspace default. What do you check first?First the project level: a `projects.<name>.schematics` entry for the same schematic overrides the workspace one. Then the command they typed, since flags beat config. Then that the key is the exact schematic name (`@schematics/angular:component`), that the option uses the camelCase schema name, and whether `cli.schematicCollections` sends `component` to a different collection.
- Why prefer the workspace block over `ng config --global` for team conventions?The workspace `angular.json` is committed, so every developer and CI job generates the same output. Global config lives in each user's home directory, differs between machines and is invisible in code review. It suits personal preferences at most.
saying these in an interview costs you the question
- Wraps ng generate in a shell alias instead of setting angular.json defaults
- Writes dashed flag names like skip-tests as keys in angular.json
- Believes an angular.json default overrides a flag typed on the command line
- Thinks the workspace-level block beats a project-level block for that project
- Confuses cli.schematicCollections with the per-schematic option defaults