You missed some details from my answer on stack overflow
No worries!
<this.tool />
has the same “dynamic” problem you were encountering before.
What you’re noticing about CaseNote
is solved by the TOOLS
-map/object concept below:
Also, copy pasting, in case stackoverflow loses threads or something:
Looking back at your error:
Unsafe dynamic component: this.tool in
routes\components\case-tools\template.hbs
is because of this code:
<div>{{component this.tool caseId=@caseId}}</div>
you can’t do {{component this.tool}}
anywhere in your app if you want to be fully strict compatible.
Going forward {{component
will not accept strings.
The laziest thing you can do today is this:
{{#let (component (ensure-safe-component this.tool)) as |Tool|}}
<Tool />
{{/let}}
which you probably don’t want to do, since to be more future proof, you’ll benefit from importing all of your possible components and creating a map to choose from like this:
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { assert } from '@ember/debug';
// import all your tools, they could come from anywhere,
// doesn't have to be sibling (./)
import Hammer from './hammer';
import Drill from './drill';
import Shovel from './shover';
const TOOLS = {
// map of:
// lower-case-hyphenated/maybe/namespaced-name => ActualComponent
hammer: Hammer,
drill: Drill,
shover: Shovel,
}
export default class CaseToolsComponent extends Component {
@tracked tool;
@action
toggleTool(toolName) {
let tool = TOOLS[toolName];
assert(`Tool named ${toolName} is not known, and cannot be used`, tool);
this.tool = tool;
}
}
and then your template would look like this
{{#if this.tool}}
{{#let (ensure-safe-component this.tool) as |Tool|}}
<Tool />
{{/let}}
{{/if}}
not that this still requires ensure-safe-component
because property accesses are dynamic.
to have the least “weirdness” you can migrate all the way to GJS, which would look like this:
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { assert } from '@ember/debug';
// import all your tools, they could come from anywhere,
// doesn't have to be sibling (./)
import Hammer from './hammer';
import Drill from './drill';
import Shovel from './shover';
const TOOLS = {
// map of:
// lower-case-hyphenated/maybe/namespaced-name => ActualComponent
hammer: Hammer,
drill: Drill,
shover: Shovel,
}
export default class CaseToolsComponent extends Component {
@tracked tool;
@action
toggleTool(toolName) {
let tool = TOOLS[toolName];
assert(`Tool named ${toolName} is not known, and cannot be used`, tool);
this.tool = tool;
}
<template>
{{#if this.tool}}
<this.tool />
{{/if}}
</template>
}