Creating complex static Markup with ember.js - javascript

I am trying to render my application template, which is getting very complicated, so I want to split it up into separate <script type="text/x-handlebars">'s
I think I want to use the {{view}} helper, but I don't know. Let's say I have this:
<script type="text/x-handlebars" data-template-name="application">
<div id="wrapper" class="clearfix">
<hgroup>
<header>
<div class="logo"></div>
<h1 id="facilityName">{{facilityName}}</h1>
<div id="sessionInfo">
<a id="userName">{{user}}</a>
<a id="logOut" href="../logout">log out</a>
</div>
</header>
</hgroup>
{{view App.breadcrumbsView}}
</div>
</script>
And I want to load this next template inside of the one above:
<script type="text/x-handlebars" id="breadcrumbs">
<div id="breadcrumbs">
<p>
Network
{{#each breadcrumbObj}}
<span>></span><a {{bindAttr href="link"}}>{{name}}</a>
{{/each}}
</p>
</div>
</script>
Right now I am trying to do this with this code from my app.js
App.breadcrumbsView = Ember.View.create({
templateName: 'breadcrumbs',
breadcrumbObj: Util.breadcrumbs()
});
This is not working and I am getting Uncaught Error: assertion failed: Unable to find view at path 'App.breadcrumbsView'
Thanks

I think that you declared your App using var keyword. So it's not visible in handlebars template.
Change this
var App = Ember.Application.create();
To this
App = Ember.Application.create();
And you have to use extend instead of create when creating your views. Because ember will handle the object lifecycle like: create, destroy, add and remove binding etc.

#Marcio is right, you should .extend() and let the framework create it for you automatically by request. Furthermore when you extend the best practice is to use capitalized names like App.BreadcrumbsView.
See here a demo how it renders correctly doing it this way.
Hope it helps.

Related

ng-include: Access child scope issue

I'm using DayPilot Scheduler in my app and i'm having the following issue.
home.html:
<div class="container-fluid">
<daypilot-scheduler id="scheduler" daypilot-config="schedulerConfig" daypilot-events="events"></daypilot-scheduler>
</div>
I access daypilot scheduler in my controller like this:
$scope.scheduler;
This works when daypilot directive is directly inside home.html like in home.html above, but returns undefined when I include daypilot with ng-include:
<div class="container-fluid">
<div ng-include src="'partials/partial1.html'"></div>
</div>
partial1.html:
<section>
<daypilot-scheduler id="scheduler" daypilot-config="schedulerConfig" daypilot-events="events"></daypilot-scheduler>
</section>
If it's included with ng-include, $scope.scheduler returns undefined. scheduler is placed under $$childTail as $$childeTail.scheduler.
What am I doing wrong, and how can I access $$childTail?
Try adding $parent. prefix to id attribute's value. So partial1.html will be:
<section>
<daypilot-scheduler id="$parent.scheduler" daypilot-config="schedulerConfig" daypilot-events="events"></daypilot-scheduler>
</section>
And in controller access it like you always did:
$scope.scheduler;

MeteorJS template placeholder

Iam getting started with MeteorJS/Iron Router/Blaze and I'm trying to figure out how to set placeholder for template.
I have a menu and a footer, which will change only partialy, but between them is the main content which should be based on current route. Point is that i need some sort of pointer, like in angular "ng-view".
Eg.
<menu></menu>
{{some sort of placeholder}}
<footer></footer>
and in router:
Router.route('/', function () {
//render some template exactly into placeholder, dont append it to the bottom
});
Maybe there is something wrong with my understanding of meteorjs templating, I just base my way of solving this problem on angular templating.
not sure I got your question but here is an answer:
You can do that with the {{> yield}} tag. It will define an dynamic area which will show the view corresponding to the current route.
You can also "design" a layout for your entire app, like you did, for example layout.html :
<template name="layout">
<div class="container">
<header class="navbar">
<div class="navbar-inner">
<a class="brand" href="{{pathFor 'home'}}">My app</a>
</div>
</header>
<div id="main" class="row-fluid">
{{> yield}}
</div>
</div>
</template>
And tell Iron-Router that your app has to fit this layout :
Router.configure({
layoutTemplate: 'layout'
});
// Then just define your routes
Router.map(function() {
this.route('home', {path: '/'});
});
You may notice I used {{pathFor 'home'}} in the layout. Iron Router let you use route "names" so it won't do anything if you change the URL.
I suggest you read an awesome book called Discover Meteor !

Handlebarsjs: render multiple passes with nested templates

I see many things that just refers me to partials which sucks because they have to built out of the layout context.
What I'm wanting to do is make nested templates
For example:
<div id="person">
{{name}}
<div id="address">
{{street}}
</div>
</div>
<script>
var outer = Handlebars.compile($('#person').html());
outer({ name: 'someone special' });
var inner = Handlebars.compile($('#address').html());
inner({ street: 'somewhere cool' });
</script>
When running this, the inner template is never rendered as the outer templating gobbles it up.
It would be nice if you could namespace nested templates like this:
{{> name}}
<div id="person">
{{name}}
{{> address}}
<div id="address">
{{street}}
</div>
{{/> address}}
</div>
{{/> name}}
<script>
var outer = Handlebars.compile($('#person').html(), 'name');
outer({ name: 'someone special' });
var inner = Handlebars.compile($('#address').html(), 'address');
inner({ street: 'somewhere cool' });
</script>
or something like this, so that when the outer renders, it will leave the address alone and let inner render address itself without removing it from the DOM.
Is anything like this possible?
The reason for this question is that I'm using backbone and want to separate out all of my small views but it compiles to one file. when the outer is templated with handlebars, everything else breaks. I don't want to use partials as that just take everything out of the flow of the html document for the designers.
EDIT
I think what I really need is a way to do {{noparse}} and from the registerHelper just return the raw html between the noparse tags
Here is a demo of a no-parse helper. To use this functionality, you will need to use a version of at least v2.0.0-alpha.1. You can get it from the handlebars build page. Here is the pull request that details about it.
Here is the relevant code.
Template
<script id="template" type="text/x-handlebars-template">
<div id="person">
{{name}}
{{{{no-parse}}}}
<div id="address">
{{street}}
</div>
{{{{/no-parse}}}}
</div>
</script>
Handlebars.registerHelper('no-parse', function(options) {
return options.fn();
});
You're missing a crucial step. You have to take the template & compile it (which you're doing) but you also have to register the partial.
Really the pattern you want to use is the partial template - where you register the inner template as a partial template then fill it with the person's address data - there is a great example here, but this also will help in your specific HTML setup.
<script id="person-template" type="text/x-handlebars-template">
{{#each person}}
{{name}}
{{> address}}
{{/each}}
</script>
<script id="address-partial" type="text/x-handlebars-template">
<div class="address">
<h2>{{street}}</h2>
</div>
</script>
<script type="text/javascript">
$(document).ready(function() {
var template = Handlebars.compile($("#person-template").html());
Handlebars.registerPartial("address", $("#address-partial").html());
template({ name: 'someone special', street: 'somewhere cool' });
}
</script>

Making divs clickable - Ember view for action on multiple elements

I am developing a Cordova application with help from Ember. I have many dynamic elements in my application. These are Bootstrap thumbnails that link to other routes when clicked.
I want to make these thumbnails clickable. If I use Views, I will have to write unique views for all the thumbnails.
I have heard about mixins. Can a general View be defined that will :
Pass a model
Render a template for a route with the model
In other words, since each view semantically performs the same action, I want to be able to do something similar to
{{#each}}
{{#view App.AllView this}}
.
{{/view}}
{{/each}}
in the template and in the view :
App.AllView = Ember.View.extend({
click: function(evt, model){
this.controllerFor('route').set('content', model);
this.transitionTo('route');
}
});
UPDATE
Following #givanse's answer, I made the following component
<script type="text/x-handlebars" data-template-name="components/thumbnail-view">
<div {{bind-attr class=class}}>
<div class="thumbnail">
<div class="caption">
{{name}}
</div>
<img {{bind-attr src=image }}>
</div>
</div>
</script>
and used it in my template :
<script type="text/x-handlebars" data-template-name="types">
<div class="row">
{{#each model}}
{{thumbnail-view action="goToCategory" class="col-xs-12" param=this name=name image=image}}
{{/each}}
</div>
</script>
with an Ember component :
Pioneer.ThumbnailViewComponent = Ember.Component.extend({
click: function(){
this.sendAction('action', this.get('param'));
}
});
The action goToCategory is defined in my ApplicationRoute
Hope this helps someone!
What you need is Components, something like:
<script data-template-name="index">
{{#each}}
{{img-thumbnail imgId="id/path/name"}}
{{/each}}
</script>
<script data-template-name="components/img-thumbnail">
{{! whatever you need to make your thumbnail }}
</script>
App.ImgThumbnailComponent = Ember.Component.extend({
// handle events, classes, etc.
});
See:
http://emberjs.com/guides/components/
http://emberjs.com/api/classes/Ember.Component.html

Ember.js - Application <div/> is rendered twice?

I'm using the following Ember.js stack:
DEBUG: -------------------------------
DEBUG: Ember : 1.1.2
DEBUG: Handlebars : 1.0.0
DEBUG: jQuery : 2.0.2
DEBUG: -------------------------------
I declared an application.hbs Handlebars template which renders my App.ApplicationView
{{#view App.ApplicationView}}
{{outlet 'modal'}} {{outlet 'notificationCollection'}}
{{#if isUserAuthenticated}}
{{render sidemenu authenticationState=isAuthenticated}}
{{outlet 'upperNotification'}}
<div id="main" class="main">
{{outlet}}
</div>
{{else}}
{{outlet}}
{{/if}}
{{/view}}
and for debugging purposes I added the gotcha to the classNames array of App.ApplicationView. When I now inspect the DOM, I can see that App.ApplicationView is rendered twice (and also boxed):
...
<div id="appRoot" class="ember-application">
<div id="ember444" class="ember-view gotcha">
<div id="ember445" class="ember-view gotcha">
...more content..
</div>
</div>
</div>
...
EDIT:
I should have tried it first, before posting it here at stackoverflow... if I remove the {{#view App.ApplicationView}}{{/view}} declaration, it get's only rendered once, as expected ;)
So, the question which remains a miracle to me is is Ember.js really generating an enclosing <div id="ember666" class="ember-view"></div> for every {{outlet}}??
Why would Ember.js handle it this way? How can I prevent it from rendering App.ApplicationView twice? And, besides that, is Ember.js really generating an enclosing <div id="ember666" class="ember-view"></div> for every {{outlet}}? (I'm seeing this behaviour within my application)
By default, yes {{outlet}} will enclose your template in a <div>. However, you can change that behavior by specifying a view class on the outlet and defining the view class' tagName property to whatever you want.
For example, the outlet
{{outlet viewClass=App.HeaderContainer}}
With view
App.HeaderContainer = Ember.ContainerView.extend({
tagName: 'header'
});
will wrap the outlet in a <header> tag.

Categories

Resources