How to configure Ember CLI to use uncss - ember.js

I have a hard time to configure Ember CLI to use uncss. The setup:
> ember new foobar
> cd foobar
> bower install --save-dev bootstrap
> ember generate route index
app/templates/index.hbs
<h1>Hello World!</h1>
Brocfile.js
/* global require, module */
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
var app = new EmberApp();
app.import('vendor/bootstrap/dist/css/bootstrap.css');
module.exports = app.toTree();
What do I have to do to use https://github.com/sindresorhus/broccoli-uncss? The assets part of http://iamstef.net/ember-cli/ says that it's easy but it doesn't describe how to actually do it.

It's not well documented in broccoli-uncss readme, but if you look at the
index.js and test.js, you would get the idea.
Basically you pass in a tree as the first parameter, and an options hash as the second parameter, And options hash should have an html option, telling where the index.html is. In your case I think what Oliver said is true. You could use the html in your dist folder. I am not sure how to integrate that with the ember-cli, but my guess is probably you need an ember-cli add-on, http://reefpoints.dockyard.com/2014/06/24/introducing_ember_cli_addons.html.
var uncss = require('broccoli-uncss');
var cssTree = uncss('dist`, {
// html file to uncss, or this could be a live link to the html
html: ['dist/index.html']
});
// you might somewhat merge this with ember-cli app tree here.
module.exports = cssTree;

Please correct me if I'm wrong...
I assume uncss won't work as expected in a "templating environment"!
Let's say you have an outer and an inner template. The outer looks like
<div class="outer">
{{outlet}}
</div>
and the inner template would look like
<h1>Text</h1>
In your css file you would maybe write something like
.outer h1 {
background: red;
}
As far as I know uncss would dismiss this css rule because uncss is not able to find it in either one of your templates.

Related

ember-bootstrap: Navbar component repeats itself 12 times

I am using ember-bootstrap's Navbar example code in a simple Ember test app:
{{#bs-navbar as |navbar|}}
<div class="navbar-header">
{{navbar.toggle}}
<a class="navbar-brand" href="#">Brand</a>
</div>
{{#navbar.content}}
{{#navbar.nav as |nav|}}
{{#nav.item}}
{{#nav.link-to "home"}}Home{{/nav.link-to}}
{{/nav.item}}
{{#nav.item}}
{{#nav.link-to "navbars"}}Navbars{{/nav.link-to}}
{{/nav.item}}
{{/navbar.nav}}
{{/navbar.content}}
{{/bs-navbar}}
However I'm having strange results; the navbar is showing up 12 times in my page. For what it's worth, the toggle button doesn't do anything either - but that might be connected to the reason the navbar appears 12 times. See the following screenshot:
Here are the steps I took to set up this project:
ember new bootstrap-test
Inside /bootstrap-test:
ember install ember-bootstrap
ember g ember-bootstrap --bootstrap-version=4
Here is the contents of my ember-cli-build.js file:
/* eslint-env node */
'use strict';
const EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function(defaults) {
let app = new EmberApp(defaults, {
'ember-bootstrap': {
'bootstrapVersion': 4,
'importBootstrapFont': false,
'importBootstrapCSS': false
}
});
// Use `app.import` to add additional libraries to the generated
// output files.
//
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.
return app.toTree();
};
Finally, I'm using ember-cli version 2.14.2. Any help to figure this out would be greatly appreciated. Thank you!
It might be caused by re-rendering due to property update in didRender or didInsertElement hook. If that's the case then you surely you will get assertion error in console.
I always look for the first error, if there is more no of errors reported in the console. that helped me a lot in my development.

How do you use Ember.js addons?

I'm evaluating Ember.js for possible use in an upcoming project. I want to see now it fares with a long list of items, so I tried to installed the ember-list-view.
I ran the command:
ember install:addon ember-list-view
The syntax seems to have changed, so I ran
ember install ember-list-view
That activates npm, which downloaded the package successfully. I can see it in node_modules. Then per the documentation I created the following:
templates/test.hbs:
{{#view 'list-view' items=model height=500 rowHeight=50 width=500}}
{{name}}
{{/view}}
routes/test.js
import Ember from 'ember';
// define index route and return some data from model
export default Ember.Route.extend({
model: function() {
var items = [];
for (var i = 0; i < 10000; i++) {
items.push({name: "Item " + i});
}
return items;
}
});
I added the route in router.js. When I go to the page, nothing shows up. According to Ember Inspector, the right template was being used and the data was there. A check on Ember.ListView in the console yield undefined.
Is there something more that needs to be done to bring in the code? Searches in the Ember and Ember-CLI documentation yielded no answer.
It looks like a problem with the list-view documentation.
There are two issues here:
The {{view}} helper is not a block helper (as far as I know. FYI a block helper is a helper that begins with {{#some-key-word}} and ends with {{/some-key-word}}) - You can't wrap content in it and have that content displayed in the view.
The list-view expects the property content not items
When you change the code to the following:
{{view 'list-view' content=model height=500 rowHeight=50 width=500}}
It works a little bit better (e.g. you can inspect the page and see item views being created) - but still not what you're expecting.
When you change the view keyword to the ember-list keyword (which ember-list-view registers as a helper) - everything works.
{{#ember-list items=model height=500 rowHeight=50 width=500}}
{{name}}
{{/ember-list}}

Ember: How do I find handlebars partial in the directory?

I am playing around with Ember.js (within Rails app) and got the the point when displaying a form. I used "partial" handlebars tag, like this:
{{partial "entity_edit_fields"}}
Ember tries to retrieve the template from _entity_edit_fields.hbs file. However, I have put all templates related to entity into separate directory. Now, I'd like to tell Ember to look to entity/_edit_fields.hbs. How can I achieve this?
To include the template entity/_edit_fields.hbs as a partial use:
{{partial "entity/edit_fields"}}
If you get stuck on something like this again, try having a look at the ember test suite. There will almost always be an example there that can help answer your question. I wasn't sure how partial worked either, so before answering I had a look at handlebars_test.js
test("should render other slash-separated templates using the {{partial}} helper", function() {
Ember.TEMPLATES["child/_subTemplate"] = Ember.Handlebars.compile("sub-template");
view = Ember.View.create({
template: Ember.Handlebars.compile('This {{partial "child/subTemplate"}} is pretty great.')
});
Ember.run(function() {
view.appendTo('#qunit-fixture');
});
equal(Ember.$.trim(view.$().text()), "This sub-template is pretty great.");
});

How do I setup an Ember View class to be appended to a particular container?

Ember.View has a nice method called .appendTo("#container") which would allow me to specify a container div for the view. However, when I use the router and .connectOutlet method, an instance of my view is created automatically based on convention and is added to the page body element by default. Is there a way to configure the class definition of the view so that upon creation it will be inside my desired #container. Here is my view:
Jimux.BuildsView = Em.View.extend({
templateName: 'builds',
appendTo: '#jimux-header', #this was just a guess and did not work. but does some propery like this exist for the view?
tagName: 'div',
listVisible: true,
...
Another way to ask this question is: how do I tell Ember router to append a view to a particular item in the dom? By default the router appends the view to the body.
And here is the router bit:
# Connect builds controller to builds view
router.get('applicationController').connectOutlet("builds","builds", Jimux.buildsController)
To clarify, I dont want to put my whole Ember app in a container. I have several views in my application, and most of them are fine directly in the body. But there are a couple like the one mentioned in this question, which I want to put inside "#application-header" div.
You can specify the root element for your application object.
window.App = Ember.Application.create({
rootElement: '#ember-app'
});
Edit:
Having re-read your question, I think you should look into named outlets, so you could do something like:
<div id="application-header">
{{outlet builds}}
</div>
{{outlet}}
well..after understanding your question, i remember having same trouble. Also, thing is i didn't find any way to do this even after going through the Ember code. But later i understood that its for good purpose only. I know you already might have come across with handlebars with which we can acheive this. If we give a view a ID to get appended, we are constraining the application and the whole use of ember becomes useless. Ok coming to you question, as far as i know, we can acheive that appending mustache templates in you div element of HTML.
<div id="jimux-header">
{{view Jimux.BuildsView}}
</div>
This way we can use the Jimux.BuildsView where ever you want and as many times possible. The Beauty of Ember you have to say...
Just add rootElement in the application object.
var App = Ember.Application.create({
rootElement: '#container'
});

Is it possible to load handlebar template with script tag? Or define handlebar templates programmatically in Ember.js

Simply enough I do not want to define all my handlebar templates in my html file
I tried this
<script type="text/x-handlebars" data-template-name="nav-bar" src="template.handlebar"></script>
But this did not work. Can I not define templates my template programmatically or even just load handlebar files so that I can reuse and also I feel it makes things a bit more maintainable.
I tried just loading them with ajax and appending them to the head, this works fine I can see it there but ember.js doesn't read it after ember has already been loaded and the templates are not defined.
Or define handlebar templates programatically in Ember.js
You can define templates programmatically by using Ember.Handlebars.compile, see http://jsfiddle.net/pangratz666/wxrxT/:
Ember.View.create({
personName: 'Dr. Tobias Fünke',
template: Ember.Handlebars.compile('Hello {{personName}}')
}).append();​
Or you add compiled templates to Ember.TEMPLATES array, see http://jsfiddle.net/pangratz666/58tFP/:
Ember.TEMPLATES['myFunkyTemplate'] = Ember.Handlebars.compile('Hello {{personName}}');
Ember.View.create({
personName: 'Dr. Tobias Fünke',
templateName: 'myFunkyTemplate'
}).append();​
I would recommend to use some tools like Richard Millan stated. Also take a look at interline/ember-skeleton which offers support for compilation of templates.
You can also patch Ember View to load templates on get
Em.View.reopen({
templateForName: function(name, type) {
if (!name) { return; }
var templates = Em.get(this, 'templates'),
template = Em.get(templates, name);
if (!template) {
$.ajax({
url: 'templates/%#.hbs'.fmt(name),
async: false
}).success(function(data) {
template = Ember.Handlebars.compile(data);
});
}
if (!template) {
throw new Em.Error('%# - Unable to find %# "%#".'.fmt(this, type, name));
}
return template;
}
});
UPDATE: Since Ember 1.0.0-pre.3 this solution probabaly no more work (maybe can be migrated to recent Ember)
So since I still wanted separate files for my templates and I didn't want to define them in strings in the javascript I hacked this together last night
It is a synchronous lazy loader, it loads all the templates first, then ember and the rest of my code,
//fake function so that every loads fine will get redefined in application.js
function initializeApp(){}
function loadTemplates(){
var arg = arguments[0],
next = Array.prototype.slice.call(arguments,1);
if(typeof arg != 'string'){
arg()
}else{
var scriptObj = document.createElement('script');
scriptObj.type = 'text/x-handlebars';
$(scriptObj).attr('data-template-name', arg.replace('.handlebars', '').substring(arg.lastIndexOf('/')+1))
$.get(arg, function(data){
scriptObj.text = data;
document.head.appendChild(scriptObj);
if(next.length > 0) loadTemplates.apply(this, next);
});
}
}
function loadScripts() {
var script = arguments[0],
scriptObj = document.createElement('script'),
next = Array.prototype.slice.call(arguments,1);
scriptObj.type = 'text/javascript';
scriptObj.src = script;
scriptObj.onload = scriptObj.onreadystatechange = (next.length > 0) ? function(){loadScripts.apply(this, next)} : function(){$(document).ready(function() {initializeApp()})};
document.head.appendChild(scriptObj);
}
function loadApp(obj){
loadTemplates.apply(this, obj.templates.concat(function(){loadScripts.apply(this,obj.scripts)}))
}
window.onload = function(){
loadApp({
templates:
[
'/javascripts/views/templates/nav-bar.handlebars',
],
scripts:
[
'https://maps.googleapis.com/maps/api/js?sensor=false&callback=initializeGoogleMaps',
'/javascripts/lib/bootstrap.js',
'/javascripts/lib/rails.js',
'/javascripts/lib/ember.js',
'/javascripts/application.js',
'/javascripts/views/nav_bar.js',
]
})
}
EDIT: I cleaned it up and made it work properly only testing in chrome though
It is possible, but you will need to precompile your templates first. This will also allow you to include all your templates within one file.
If you are using Rails, you can use the ember-rails gem to do it for you.
Otherwise you can follow these instructions on how to precompile handlebars
Later on, you will need to include the javascript file.
<script src="path/to/compiled/templates.js" type="text/javascript"></script>
If you load your templates into the DOM before loading Ember, then you don't need to compile or register your templates. Ember will come along after and do it for you.
Here is an article showing how:
http://weboriented.wordpress.com/2012/09/02/loading-handlebars-templates-in-ember-using-curl-js/
Here's another solution, inside your Ember view/component:
var viewClass = Ember.View.extend({ templateName: this.get('contentTemplate') });
var view = this.createChildView(viewClass);
var html = view.renderToBuffer().buffer;
This is an old question, so all the answers are a bit outdated. With Ember CLI templates are auto loaded by naming convention as require.js modules. It's a bit odd, since you write proposed ES6 import syntax and the build transpiles it into require.js syntax, but it works really well.
It is possible, and yes, you can do it without usage of another another another tool, just using ember.js and nothing else. i did it like this:
1) html code. note that all handlebars files need to be loaded before using any of them. here, its just one file named handlebars.js
<body>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.2.min.js"><\/script>')</script>
<script src="js/libs/ember-0.9.8.1.min.js"></script>
<script src="js/handlebars.js"></script>
<script src="js/app.js"></script>
</body>
2) this file handlebars.js contains the following, using the compiler of ember
var src = "Hello, <b>{{name}}</b>";
Em.TEMPLATES["say-hello"] = Em.Handlebars.compile(src);
3) and then inside your app.js file, just use it as it were available (which it is):
var hu = Em.View.create({
templateName: "say-hello",
name: "Allô",
mouseDown: function() {
window.alert("hello world!");
}
});
hu.appendTo("body");