How to fix template linting errors (i.e. no-action) for classical components

I upgraded my app from Ember version 3.0.0 to Ember 3.16 (edition Octane). Now I have lots of template linting errors and want to know how to continue. I cannot migrate all components to glimmer-components. But I want to get rid of the linting-errors. I.e. no-action: Is it possible to fix this error for classical components? Is it possible to disable the warnings for specific components?

Do you have some proposals? Thanks

Yes, for the most part these linting errors can be resolved without the full on move to @glimmer/component. In fact, the linting system doesn’t even know what kind of component a given template invocation is!

The best way to help here would be for you to share specific lint failures (the template snippet that causes them). With that we could should alternates that are not going to trigger issues and would feel more “Octaney”.


Generally speaking, the no-action rule is trying to guide you away from the various forms of {{action towards tools like {{on and {{fn. Checkout its documentation here. I’d definitely love to increase the docs to better explain the various scenarios, mind opening an issue (or PR and we can work through the details)?

1 Like

Thanks @rwjblue!

Yes I know, I accomplished to solve the vast majority of the errors without a full move to @glimmer/component.

The no-action-rule cannot be satisfied without a full move. Am I right? It would be great if we could add an octane-specific info at the rule-docs . WDYT?

Nope. This is incorrect. :smile_cat: I’d love to show you, but I’d need an actual template snippet that is causing the failure so that I can show how you could write it differently.

I’d absolutely love help documenting what we identify as a result of this conversation! However, I don’t think it is “octane specific”. This rule can be avoided without Octane (though it would require recentish Ember or usage of fn and on polyfills).

1 Like

Nope. This is incorrect. :smile_cat: I’d love to show you, but I’d need an actual template snippet that is causing the failure so that I can show how you could write it differently.

Ok, great to hear. I tried to fix it, and ran into errors. Here’s a snippet:

  <t.body @rows={{rows}} as |body|>
    <body.row as |row|>
      <row.cell as |cellValue columnValue rowValue|>
        {{component columnValue.cellComponent
          onView=(action "viewUser")
        }}
      </row.cell>
    </body.row>
  </t.body>

OK, awesome thanks for the snippet! There are a few different ways to tackle this, but the thing I’d suggest is to change your JS class to do the binding for you instead of relying on the (action call in the template.

So your component would move from this:

import Component from '@ember/component';
import { action } from '@ember/object';

export default Component.extend({
  actions: {
    viewUser() {
      // your code here...
    }
  }
});

To something like this (showing both classic syntax and class syntax, both work regardless of Octane status assuming Ember >= 3.12):

import Component from '@ember/component';
import { action } from '@ember/object';

// classic syntax
export default Component.extend({
  viewUser: action(function() {
    // your code here...
  }),
});

// native class syntax
export default class MyThing extends Component {
  @action viewUser() {
    // your code here...
  }
}

Then finally, you’d update your template invocation to:

  <t.body @rows={{rows}} as |body|>
    <body.row as |row|>
      <row.cell as |cellValue columnValue rowValue|>
        {{component columnValue.cellComponent
          onView=this.viewUser
        }}
      </row.cell>
    </body.row>
  </t.body>
1 Like

@rwjblue Thank you for that example. That’s awesome.

Here’s another snippet, where “Octane’s”fn-helper in combination with the on-modifier would be used. toggle comes from https://github.com/DockYard/ember-composable-helpers#toggle

<div class="ui teal icon button" role="button" onclick={{action (toggle "sidebar" this)}}>
  <i class="content icon"></i>
</div>

How to fix this?

To to be super clear, on and fn are not limited to usage within applications that are opting in to Octane. They are available to anyone using Ember >= 3.11 (and can be used much farther back if you add the ember-on-modifier and ember-fn-helper-polyfill).


FWIW, in this example you didn’t actually need (action to begin with (you could have used onclick={{toggle 'isExpanded' this}} directly).

OK, now down to how to move forward. I would migrate to this template snippet:

<div class="ui teal icon button" role="button" {{on 'click' (toggle "sidebar" this)}}>
  <i class="content icon"></i>
</div>

This works because toggle (and AFAICT all of the helpers in ember-composable-helpers) returns a function, {{on accepts a function. :tada:

1 Like

@rwjblue Thanks. You helped me a lot!