Not generate .js file

While generate component through cli comment.

ember generate component component-name

Message :
installing component
create app\components\testing.hbs
skip app/components/testing.js
tip to add a class, run ember generate component-class testing
installing component-test
create tests\integration\components\testing-test.js

it doesn’t generate .js file and component inside template.

How to solve this?

First, welcome!

Second, any time you have a question about the behavior of Ember CLI you can type ember help—up to and including about specific commands! So, here, you can run ember help generate component, and it’ll print this:


ember help generate component
Requested ember-cli commands:

ember generate <blueprint> <options...>
  Generates new code from blueprints.
  aliases: g
  --dry-run (Boolean) (Default: false)
    aliases: -d
  --verbose (Boolean) (Default: false)
    aliases: -v
  --pod (Boolean) (Default: false)
    aliases: -p, -pods
  --classic (Boolean) (Default: false)
    aliases: -c
  --dummy (Boolean) (Default: false)
    aliases: -dum, -id
  --in-repo-addon (String) (Default: null)
    aliases: --in-repo <value>, -ir <value>
  --in (String) (Default: null) Runs a blueprint against an in repo addon. A path is expected, relative to the root of the project.

      component <name> <options...>
        Generates a component.
        --path (String) (Default: components)
          aliases: --no-path (--path="")
        --component-class (@ember/component, @glimmer/component, @ember/component/template-only, "") (Default: --no-component-class)
          aliases: -cc (--component-class=@ember/component), -gc (--component-class=@glimmer/component), -tc (--component-class=@ember/component/template-only), -nc (--component-class=""), --no-component-class (--component-class=""), --with-component-class (--component-class=@glimmer/component)
        --component-structure (flat, nested, classic) (Default: flat)
          aliases: -fs (--component-structure=flat), -ns (--component-structure=nested), -cs (--component-structure=classic)

As you can see, the command you want to get a backing class is ember generate component <component name> --component-class @glimmer/component. The short version of that would be ember g component <component name> -gc.

Now, you might be wondering: why is the default to not generate a backing class? Since the launch of Ember Octane, Ember CLI defaults to generating “template-only” components because they’re the right starting point:

  • very often you don’t actually need a backing class: you can do everything you need to just by passing in arguments (including actions)
  • template-only components have the best performance—the lowest memory usage and the fastest to render
  • once you have a backing class, it’s a “state magnet”: it’s tempting to make components have their own local state whether or not that’s actually the best fit for your app’s data flow
  • you can also always generate a backing class later by using the ember generate component-class command!
2 Likes

I am still a bit dumbfounded that the default is not to create a backing class. The component must surely be doing absolutely nothing if you don’t need a backing class. I’ve never yet not needed one.

You can pass arguments in but you usually need to filter it, order it etc If all you have is static html why even bother using ember.js for it.

Template-only components are not static, they’re just not stateful. That’s a key difference: there are tons of interesting things you can do in rendering HTML without stateful components. The code can be quite dynamic in the HTML it generates, depending on the arguments passed in. And many of the kinds of transformations you might want can be done in a parent component or in helpers. (In fact, there are whole programming paradigms and languages where this is how all rendering works: Elm, for example.)

By way of analogy: a template-only component is just like a function in JS. A JS function can do a lot of things, and isn’t “static” at all. The same is true of templates! And in fact, a template-only component is just a function in the underlying implementation of the template language.

As for never not needing one: I believe you! However, I’ll also note that we have found a great many places where they’re useful in the app that powers LinkedIn.com! In fact, many components which used to have backing classes before we moved to Octane and Glimmer components don’t anymore: more and more of our components over time are template-only.

Thanks. It would be interesting to see the sort of case where previously you had a JS file and then was gotten rid of?

I find it’s very common to have had backing classes which were largely present to do things in didInsertElement or didReceiveAttrs. Where they were using/working with the element, switching to a custom modifier often eliminates the need for the backing class entirely. Where they were using didReceiveAttrs to perform side effects (API calls, etc.), refactoring to one-way data flow also often ends up removing the need for didReceiveAttrs.

There’s a good example here, which I extracted from our app a while back. Here the original Ember Classic version made very heavy use of backing classes (including mixins and even an observer). The Octane implementation still has one backing class, but one of the components became a template-only component: the refactors that let it move to Octane also made the backing class extraneous.

Helper addons like ember-truth-helpers and ember-composable-helpers are extremely powerful here as you can replace most basic computed properties (especially CP macros) with them.

I would add that in many cases we are finding that places people tended to reach for components in the Ember Classic world, we are now solving with helpers. This happened just today for a place or an engineer was stumped about how to deal with what he would have used the didReceiveAttrs hook for in the past. His initial thought was to reach for the did-update modifier, but the actual solution ended up being having a small helper which did just one thing, and solved the entire problem cleanly so that the entire backing class for the component was gone. There was much less state to manage and less total code this way, as well as cleaner separation of concerns. Wins all around.

I’m still dumbfounded that it doesn’t create js by default you have to add --component-class at the end.

If you have a button that responds to a click…how to I get it to do something on a click in the component if there is no js!? Basic usage!

:man_shrugging: i still think the default makes sense, i generate a lot of template only components and don’t want to go back and delete unnecessary backing classes…

it’s only 3 extra keystrokes to add a backing class:

ember g component <name> -gc

and if that is unbearable you could make yourself a custom script or shell alias or something

1 Like