cannot load a custom helper - ember.js

I have wrote a highlight helper follow the ember guides.
app/helpers/highlight.js
export default Ember.Handlebars.makeBoundHelper( function(value, options) {
var escaped = Handlebars.Utils.escapeExpression(value);
return new Ember.Handlebars.SafeString('<span class="highlight">' + escaped + '</span>');
});
I invoke the helper in the application template with {{highlight name}} and declare the name in application controller . When visit the index page I got this error
Assertion Failed: A helper named 'highlight' could not be found. Seems the helper is not loaded. Is there any configuration to load the helper ?

I assume that you use ember-cli, as you tagged it this way.
Plain ember and ember-cli are using different resolvers (basiclly mechanisms that search for files in proper directories) and thus have a little bit different name conventions. Helpers in ember-cli must have a dash in their name.
Take notice that if you only put the code you mentioned in your question, this file will have no information what is Ember. You still need to import Ember using modules. Very nice introduction can be found here.
To sum up, change your helper file name to one that includes a dash and the helper will be recognized across the environment.

Related

Ember v. 2.x: watch vendor folder

I'm developing an Ember-JS application with a lot of JavaScript that performs of all kind of UX and styling tasks.
Because these tasks fall out of the scope the MVC-logic, I've put them into modules that I put in the vendor map.
Putting them into the Vendor folder doesn't mean I'm done tweaking these files, but to test them, I'm required to re-start the ember-server over and over again.
How can I make Ember watch these JS-files in my vendor folder and re-compile them when I change them?
The following page answers for Ember v. 1, but doesn't apply to Ember 2.0: https://discuss.emberjs.com/t/solved-watch-addon-directory-for-changes/6410/4
I also tried creating an addon, but ember (cli) answers with: “You cannot use the addon command inside an ember-cli project.”
It took me a while to connect all the pieces of information scattered over internet, but using #Lux 's anwers, this is what I found out.
1) Using the ember-cli, I generate a 'utility' (hence the utils folder):
ember g util grid-layout
This gives you a JS-file “app/utils/grid-layout.js” template to fill in. In my case, it was a matter of…
2) copy-paste the body of the function I created earlier, into the body of the function that ember-cli came up with:
export default function gridLayout(tree) {
…
return tree
}
3) Importing the function in the controller, in my case controllers/index.js. I found different examples on how to do this, with and without curly braces and using different paths to the module file, but this is what made it work for me:
import Ember from "ember";
import gridLayout from "../utils/grid-layout";
export default Ember.Controller.extend({…
Links:
https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Statements/export
https://blog.abuiles.com/blog/2014/10/03/working-with-javascript-plugins-in-ember-cli/
In ember-cli version 2.11.0 by default its watching vendor foler.
https://github.com/ember-cli/ember-cli/pull/6436

Addon not working

I have an Ember Addon which I've put up at Github here:
https://github.com/lifegadget/ember-dictionary
It passes all its unit tests and in a non addon form it is working fine in one of my projects but I'd like to lift it out the project and be able to use it as an addon. Still I'm clearly missing a step in how to expose the two Ember classes. This can be seen in the dummy app which tries to create a very simple model like so:
import DS from 'ember-data';
import DictionaryModel from 'ember-dictionary';
export default DictionaryModel.extend({
foo: DS.attr('string')
});
Then when the route (tests/dummy/routes/index.js) tries to use the model I get the following error:
Error while processing route: index Cannot read property 'extend' of undefined TypeError: Cannot read property 'extend' of undefined
To me this feels like a ES6/namespacing issue but I'm not sure how to overcome it. I did try the following more explicit import statement:
import DictionaryModel from 'ember-dictionary/models/dictionary-model';
but the same error occurred. Any help would be greatly appreciated.
I have bumped into enough walls that I think I can at least partially answer my question but some questions still remain so I won't mark this answer correct with the hope that others may post a more complete answer.
The first distinction I realised I hadn't been making clear enough for myself was whether to target the Ember App's namespace or to target an independent namespace for the addon. Classes defined in the app directory of the addon will be available to any application which uses the Addon in it's own namespace. In contrast, classes in the addon directory will be namespaced to the addon's namespace.
I have seen a lot people define classes in the addon's app directory and then proxy it through to the addon directory with something like:
// addon/mixins/dictionary.js
import DictionaryMixin from 'ember-dictionary/mixins/dictionary';
export default DictionaryMixin;
Although I've seen this I am still having problems getting these external namespaced classes to work. I think there may be another step needed to add a index.js entry point for the addon and then export these classes there. In any event, I'll leave this area alone as I decided to get the internal namespaced solution working first.
My next problem in the internal namespaced solution was centered around the dummy application that gets built as part of the addon creation process. I wanted this dummy application to have a model which would use the Mixin I created in the addon and I thought I'd be able to refer to it as:
import DictionaryMixin from 'ember-dictionary/mixins/dictionary';
but this couldn't be resolved by the Dummy test application so I had to resort to:
import DictionaryMixin from '../mixins/dictionary';
Which I guess is appropriate considering that my "external namespaced solution" isn't working yet ... falling back to the internally namespaced solution was required.

Qunit testing an ember controller, located in a file that contains multiple controllers?

So, I've been trying to qunit test an Ember controller, The problem is, The controller is inside a coffeeScript file, that contains multiple controllers.
Now, The ember testing guide says, In order to test a controller, I should use the 'moduleFor' helper like so:
moduleFor(fullName [, description [, callbacks]])
In my case, the full name is say: "CustomersIndexController" , But because it's included in "customers_controller.coffee" that in it self includes multiple controller, Testing it became problematic .
After an Endless digging online, I found out (Please correct me if I'm wrong) that the resolver cares only about the file name, not about the name that 'export default myModel' provides
To make it more clear, Here is my "customers_controller.coffee" :
`export { CustomersIndexController, CustomersItemController }`
CustomersIndexController = Ember.ArrayController.extend
#Code goes here ......
CustomerItemController = Ember.ObjectController.extend
#Code goes here .....
And here is the customers-controller-test.coffee file :
`import { test, moduleFor } from 'ember-qunit';`
moduleFor("controller:customers-index-controller", 'C Controller')
test "it's an App.Controller", -> ok(#subject())
I've tried all the ideas that my brain could produce...without any luck(changing the controller name from camelCase to dasherized, to absolute path, even tried importing customers_controller.coffee), But I keep getting:
Setup failed on it's a App.Controller: Attempting to register an unknown factory: `controller:customers-index-controller`
Any Help/Advice/Links are highly appreciated.
You should be able to defined it in lower camelCase.
moduleFor('controller:postsIndex', 'Posts Index Controller');
http://jsbin.com/ruhalota/1/edit
If you take a look at the documentation for the resolver with ember-cli, you'll see that it does indeed only care about the names of the files, and what is the default export of them: http://www.ember-cli.com/#using-modules
In your case, you'll need to split your controllers into multiple files, so the resolver can find and instantiate them properly. So, the two files would be:
app/controllers/customers/index.coffee
app/controllers/customers/item.coffee
This is all assuming you are using ember-cli. If you are still using ember-app-kit, you might need to adjust this slightly, but the same basic idea should apply.

Ember.js helper with moment.js (using ember-cli) : Handlebars error: Could not find property

I'm trying to use moment.js in my ember.js app (built with ember-cli), I have a trouble with this error
Handlebars error: Could not find property 'formatDate' on object
I think it's same as this error How to use Custom helpers in ember-app-kit? but I already did the same approach but not working yet. Anyone got same error? Please help me to figure out.
I put
app.import('vendor/momentjs/moment.js'); in Brocfile.js
and
"moment": true in .jshintrc as in ember-cli documentation,
and I used the helper {{formatDate date}} in PostsTemplate
I created a helper app/helpers/formatDate.js
var formatDate = Ember.Handlebars.makeBoundHelper(function(date) {
return moment(date).fromNow();
});
export default formatDate;
I also tried this syntax in app/helpers/formatDate.js, but neither works and both get same error
export default Ember.Handlebars.registerBoundHelper('formatDate',function(date) {
return moment(date).fromNow();
});
I think your file name 'formatDate.js' has the wrong format. Try 'format-date.js' and it should work.
Excerpt from http://iamstef.net/ember-cli/:
Handlebars helpers will only be found automatically by the resolver if their name contains a dash (reverse-word, translate-text, etc.) This is the result of a choice that was made in Ember, to help both disambiguate properties from helpers, and to mitigate the performance hit of helper resolution for all bindings.
Use your new 'format-date' helper like this:
{{format-date "29/05/2014"}}
I ran into this symptom as well and had a different solution.
I had a helper in app/helpers/fh.js called 'fh' in order to be able to use it I needed to add it to the controller as follows
import fh from '../helpers/fh';
If I didn't have the import line I would get the following error:
"Handlebars error: Could not find property 'fh' on object"

ember js development mode runtime template compile?

I'm learning to work with Ember and Grunt precompiled HBS templates, but want to also run in a 'developer mode' where the the App will compile the HBS's at runtime, if it doesn't find them.
I've read about a few ways to go about this and am trying to do it with '$.ajax()' and 'Ember.Handlebars.compile(data)' where each template returned is added to the Ember.TEMPLATES array. This won't work off the file system, so I test it on a localhost tomcat where the Ember App is added to webapps/ROOT.
I'm working with a demo 'user admin' App I found online which uses a couple of components, helpers and 'generated controllers'. So the Templates compile OK, but there are problems with Helper registration, such as:
Handlebars error: Could not find property 'modal-box' on object (generated modal-demo controller).
...so after adding the Component Template to the Templates array, I try to register it by name:
if (templateName == 'components/modal-box') {
Ember.Handlebars.helper('modal-box', function(value, options) {
var escaped = Handlebars.Utils.escapeExpression(value);
return new Handlebars.SafeString(tmpl);
});
}
...but then I get this new error:
registerBoundHelper-generated helpers do not support use with Handlebars blocks.
"Template was precompiled with an older version of Handlebars than the current runtime."
This is all done in an 'App create ready' function which iterates a list of template names, which I'd like to further develop to where it reads the template file names dynamically. The Grunt process also compacts the CSS and concatenates the scripts, so I would want to work out a 'developer mode' process for these too. But right now I'm focused on the HBS Templates & Components.
I'm thinking this must be a FAQ so am wondering if the community has arrived at a best practice for this sort of runtime compile for development?
If not how can I resolve my issue with getting the component template helper generated controllers registered correctly?
They just need to be registered before the other templates are compiled.
Em.TEMPLATES["components/cow-dude"] = Ember.Handlebars.compile("I'm a cow");
App = Ember.Application.create();
http://emberjs.jsbin.com/apIRef/28/edit
Order of operations is important, if it compiles the other templates first, they will just assume cow-dude is a property on the model in context (which will probably be undefined) (http://emberjs.jsbin.com/apIRef/27/edit). That being said, if you are going to lazy load componenets/helpers, those need to be loaded before any of their dependencies (Ember handles this all for you when you just toss them all in at once).
Additionally it sounds like you are using two different versions of Handlebars, which is why it's giving you the Template was precompiled with an older version of Handlebars than the current runtime.
I wrote up a similar response to someone else that might be of use to you: Ember.js with external handlebars template