How to write Helpers in HTMLBars? - javascript

After the latest release of EmberJS v1.9.0 I am trying to move from Handlebars to HTMLbars. What I am finding very challenging is lack of documentation.
I am trying to implement very simple helpers.
For example take this handlebars helpers:
HTML
<div id="main"></div>
<script type="text/x-handlebars" data-template-name="index">
{{logIt test}}
<h1>{{test}}</h1>
</script>
JS
App = Ember.Application.create({
rootElement: '#main'
});
App.IndexRoute = Ember.Route.extend({
setupController: function(controller){
controller.set('test', 'mytest');
}
});
Ember.Handlebars.registerHelper("logIt", function(something) {
console.log(something);
});
Js Fiddle: http://jsfiddle.net/sisir/p463q2L8/
How do I convert it to htmlbars?

As of Ember 1.13, there are two APIs: http://emberjs.com/blog/2015/06/12/ember-1-13-0-released.html#toc_new-ember-js-helper-api
The simplest and more common syntax is now this:
export default Ember.Helper.helper(function(params, hash) {
return params.join(' ');
});
Helpers receive two arguments: params are the ordered params passed to a helper, and hash contains the key-value options, for example title="Mr.".

As of Ember 1.10.0, this question is solved by doing Ember.HTMLBars.makeBoundHelper(theHelperFunction).
Edit: since Ember 1.13.6 (July 31, 2015), using this is flagged as deprecated.
DEPRECATION: Using Ember.HTMLBars._registerHelper is deprecated. Helpers (even dashless ones) are automatically resolved. [deprecation id: ember-htmlbars.register-helper]

I believe you can just use Ember.Handlebars.helper which is what is in the latest emberjs guides. This jsbin uses htmlbars and it works. This is the helper in the jsbin
AppLogItHelper = Ember.Handlebars.helper("logIt", function(something){
console.log(something);
});
If you are using ember-cli it will auto generate one for you but that uses Ember.Handlebars.makeBoundHelper which doesn't work in the jsbin but works in my ember-cli app.

Very an important novelty is HTMLBars have subexpression! Since Ember 1.10+ was switched to HTMLBars and you should use Ember.HTMLBars.makeBoundHelper instead Ember.Handlebars.registerHelper. But you can still use Ember.Handlebars.registerHelper from Ember 1.10.1 version
New approach:
App.XEqHelper = Ember.HTMLBars.makeBoundHelper(function(params, hash, options, env) {
return params[0] === params[1];
});
it call from templates as:
{{#if (x-eq order 'delivery_order')}}
Need a delivery
{{/if}}

Related

Unable to render partials with handlebars and assemblefile.js

I'm using the updated documentation for Assemble.js and am having a hard time getting a clear picture of how to use Partial includes within subfolders using Handlebars.
The only meaningful reference I've found to partial config in assemblefile.js is in the deprecated gulp-assemble doc site.
Assemble.io isn't helpful since it's not up-to-date with the latest github repo.
Here's my assemblefile.js:
'use strict';
var assemble = require('assemble');
var app = assemble();
var streamRename = require('stream-rename');
var markdown = require('helper-markdown');
app.helper('markdown', require('helper-markdown'));
app.task('load', function(callback) {
app.partials(['templates/partials/*.hbs']);
app.pages(['templates/*.hbs']);
callback();
})
app.task('assemble', ['load'], function() {
return app.toStream('pages')
.pipe(app.renderFile())
.pipe(streamRename({extname:'.html'}))
.pipe(app.dest("./"));
});
app.task('default', ['assemble']);
module.exports = app;
My file structure:
root
---/templates
------index.hbs
------/partials
---------myPartial.hbs
When I try to invoke the partial from index.hbs with:
{{> partials/myPartial.hbs}}
The assemble task generates this error:
The partial partials/myPartial.hbs could not be found
How do I include Handlebars partials within subdirectories with a simple Assemble build?
Just use the stem of the partial filename:
{{> myPartial }}
There's also a built-in helper called partial that attempts to find the partial by the key (like myPartial) or other properties like path (partials/myPartial.hbs)
{{partial 'myPartial'}}
More information about how the templates work together can be found in the templates readme. These docs are also linked to from the assemble readme.

How to create an enums service in ember

I want to create a service of enums in ember so that I only have to inject it to use it everywhere. Is there a good way to do it?
Thanks.
Oh I found the solution.
I've doing the right thing but the ember serve is not that smart..
Steps:
just use: ember g service enums
and add an initializer with: ember g initializer enums
in newly created enums initializer, put
export default {
name: 'titleService',
initialize: function(application) {
application.inject('route', 'enums', 'service:enums');
}
};
restart the ember server and you get yourself an enums service
I think this would work also, in your service code you add Enumerable mixin
export default Ember.Service.extend(Ember.Enumerable, {
length: // ...
nextOjbect: // ..
next: // ...
value: // ...
}
According to the docs you will need to implement nextObject() and length. Ember service is just Ember object so I think this is much cleaner solution
http://emberjs.com/api/classes/Ember.Enumerable.html#toc_writing-your-own-enumerable
Let me know if this worked for you....

How do I convert these initializers to instance initializers when upgrading from ember.js 1.11.3 to 1.12 to remove the deprecation warnings?

I'm in the process of upgrading our ember/ember-cli version from 1.11.3 to 1.12, in prep for hitting 1.13 and 2.0 soon after.
However, I'm having some trouble deciphering exactly what has changed wrt initializers and instance-initializers... have looked over the docs and read quite a lot of posts, but still not clear on how these work. I'm particularly confused about the difference between application.register and container.register, and when I should be using application, container, or instance.
Going from ember.js 1.11.3 to ember.js 1.12, ember-cli 0.2.2 to ember-cli 0.2.7
My initializers are fairly simple, can someone help me convert them? A brief overview or link to such on how exactly ember works during the initialization / instance-initialization process would also be helpful.
Here are my existing initializers from 1.11.3:
initializers/auth.js
import Ember from 'ember';
import Session from 'simple-auth/session';
import CustomAuthenticator from 'soxhub-client/authenticators/soxhub';
import CustomAuthorizer from 'soxhub-client/authenticators/soxhub';
export default {
name: 'authentication',
before: 'simple-auth',
initialize: function(container, application) {
Session.reopen({
user: function() {
var userId = this.get('user_id');
if (!Ember.isEmpty(userId)) {
return container.lookup('store:application').find('user', userId);
}
}.property('accountId')
});
console.log('registering authenticator on container');
container.register('authenticator:soxhub', CustomAuthenticator);
container.register('authorizer:soxhub', CustomAuthorizer);
}
};
initializers/inject-session-into-service.js
import Ember from 'ember';
export default {
name: 'inject-session-into-service',
after: 'simple-auth',
initialize: function(container, application) {
console.log('ran initializer for sesion');
application.inject('service:pusher', 'session', 'simple-auth-session:main');
}
};
initializers/inject-store-into-component.js
export default {
name: "injectStoreIntoComponent",
after: "store",
initialize: function(container, application) {
console.log('injecting store onto component');
// container.typeInjection('component', 'store', 'store:main');
application.inject('component', 'store', 'store:application');
}
};
I'm not familiar with the initializers, but I saw this Ember NYC Meetup Talk which addresses initializers and I think it might help you. The whole talk is very interesting but I linked to part where initializers are addressed
Looking at your initializers, I would say that this snippet
Session.reopen({
user: function() {
var userId = this.get('user_id');
if (!Ember.isEmpty(userId)) {
return container.lookup('store:application').find('user', userId);
}
}.property('accountId')
});
Could possibly be moved the the beforeModel hook on the application route. And do something like this?
beforeModel() {
let user = this.get('store').find('user', accountId);
this.get('session').set('user', user);
}
From that talk, I think you're not supposed to use "*.lookup" but you can still use inject/register.
Also, from the ember guides for the latest versions (2.0+). The initializers don't get the containeranymore, but you the application which has the methods to inject/register.
Hope that helps

Weird error with Ember controllers

I'm on Ember Cli version: 0.2.3
I'm currently exploring with Ember, and trying a very simple app.
I have this in my templates/about.hbs
<h1>About</h1>
<p>I'll write something interesting here</p>
<button type="btn btn=primary"{{action 'clickMe'}}>Click me!</button>
and in my controllers/about_controller.js
Blogger.AboutController = Ember.Controller.extend({
actions: {
clickMe: function() {
alert('Something something');
}
}
});
when I click on the button i get this error, I checked the syntax and can't seem to catch what's wrong. I need some fresh eyes.
Uncaught Error: Nothing handled the action 'clickMe'. If you did handle the action, this error can be caused by returning true from an action handler in a controller, causing the action to bubble.
Now, I understand what the message is saying, but I don't know how to fix it yet.
Ember probably can not find your controller. You can debug this using ember inspector. In any case you should be using ES6 conventions inside your ember cli project. You can get to know more about the subject here.
Anyway, try to create about controller using command line by typing
ember generate controller about
and then add your action manually.
Are you using ember cli or Ember starter Kit for your program.
If you are using Ember cli then you should create files like -
app/templates/about.hbs
app/controllers/about.js
and you should make one entry in app/router.js too[I think you must have done that.]
Entry in router.js-
Router.map(function() {
this.route('about');
});
Now your template/about.hbs should be-
<h1>About</h1>
<p>I'll write something interesting here</p>
<button {{action 'clickMe'}}>Click me!</button>
and controllers/about.js should be-
import Ember from 'ember';
export default Ember.ObjectController.extend({
actions:{
clickMe: function() {
alert('Something something');
}
}
});
After making all the above changes execute below command on CMD -
ember server (this should start the server)
Your code should work if you do it in above pattern.
Naming conventions are very important in Ember.

Building Flux/React application without NodeJs EventEmitter

Hi I'm trying to build a Flux/React application with a go-lang back-end. I have been following a tutorial I found here. But I have a problem when building the store. In the tutorial something like this is used to create a base for the store.
var ProductStore = _.extend({}, EventEmitter.prototype, {...});
The problem I have is I do not have access to the EventEmitter library which I understand is a Nodejs lib? Is there an alternative I can use?
You can use NodeJS libraries in the browser! Take a look at browserify.
First some code:
// index.js
var EventEmitter = require("events").EventEmitter;
var ProductStore = function() {};
ProductStore.prototype = new EventEmitter;
Then you run browserify on it:
browserify index.js > bundle.js
Also worth a look is WebPack which does the same thing. (but has some additional features)
Well if you are using the flux implementation given by Facebook (https://github.com/facebook/flux), you can actually extends their FluxStore class which comes with a build in eventEmitter.
The only thing if you want to do that is you must use es6 classes (and use babel to transpile to es5).
The good thing about it is that you don't have to implement the addListener removeListener and emitChange methods, and that's very DRY :)
With this solution, your stores will end up looking like that :
var FluxStore = require("flux/utils").Store,
thing;
class ThingStore extends FluxStore {
getThing() {
return thing;
}
__onDispatch(payload) {
//your code
}
}

Categories