Search code examples
javascriptember.jsglimmer.js

Dynamic template arguments for an Ember component


I've run into a situation with a glimmer component that renders a LinkTo component within. The issue is that LinkTo treats the case where @model={{undefined}} and the case of omitting the @model argument as 2 different cases. This is because the default value for it is a special value of UNDEFINED. When this happens the component uses JS to make the transition i.e. the href is # and so you can't use browser commands like Open in new tab to open the resulting link. So I tried using inline ifs

    <LinkTo @route={{@route}}
    {{if @model (concat "@model={{" @model "}}")}}
    {{if @query (concat "@query={{" @query "}}")}}
    >
    {{yield}}
    </LinkTo>

however, much as I expected this does not work. I've had to resort to having multiple if blocks like so:

    {{#if @model}}
      <LinkTo @route={{@route}} @model={{@model}} @query={{@query}} @replace={{@replace}}>
        {{yield}}
      </LinkTo>
    {{else if @models}}
      <LinkTo @route={{@route}} @models={{@models}} @query={{@query}} @replace={{@replace}}>
        {{yield}}
      </LinkTo>
    {{else}}
      <LinkTo @route={{@route}} @query={{@query}} @replace={{@replace}}>
        {{yield}}
      </LinkTo>
    {{/if}}

This works, but is rather verbose and requires a lot of duplication. Is there a way to dynamically pass @model only when it is specified to the parent component?


Solution

  • I think what you should do is always to rely on @models.

    You could do this:

    <LinkTo @route={{@route}} @models={{this.models}}>{{yield}}</LinkTo>
    

    and in js:

    get models() {
      if(this.args.model) {
        return [this.args.model];
      }
      if(this.args.models) {
        return this.args.models;
      }
      return [];
    }