Ember Handlebars template does not work after it initially loads - javascript

I recently went from ember rc8 to 1.0.0 and to ember-data beta-2. When I did this, there were several error messages but this one I cannot figure out:
Uncaught Error: Cannot perform operations on a Metamorph that is not in the DOM.
I am currently in the process of getting into a jsbin to debug but in the meantime I created this album to demonstrate what is going on : Album
Here is the Route when the error is displayed:
App.BadgeBasicRoute = Ember.Route.extend({
model: function(params) {
return this.modelFor('badge');
}
})
and its parent route:
App.BadgeRoute = Ember.Route.extend({
model: function(params) {
return this.store.find('badge',params.badge_id);
},
afterModel: function(params) {
return this.transitionTo('badge.basic', params)
}
});
and here are the templates:
BadgeBasic.hbs
<div class="row">
<div class="col col-lg-12">
<h3>Basic Info</h3>
<hr>
<div class="row page-header-title">
<div class="col col-lg-11">
<h4>Tag Line</h4>
</div>
{{! test comment }}
{{#view App.EditTagLineView}}
<h4 {{bindAttr class=":glyphicon isEditingTagLine:glyphicon-nothing:glyphicon-pencil :edit-button"}}></h4>
{{/view}}
</div>
<p>
{{#if isEditingTagLine}}
{{view Ember.TextField valueBinding="short_description" class="form-control" style="padding-top:10px"}}
<hr>
<button {{action saveTagLine}} class="btn btn-success">Save</button>
{{else}}
{{#if short_description}}
{{short_description}}
{{else}}
No tag line provided
{{/if}}
{{/if}}
</p>
<div class="row page-header-title">
<div class="col col-lg-11">
<h4>
Description
</h4>
</div>
{{#view App.EditDescriptionView}}
<h4 {{bindAttr class=":glyphicon isEditingDescription:glyphicon-nothing:glyphicon-pencil :edit-button"}}></h4>
{{/view}}
</div>
<p>
{{#if isEditingDescription}}
{{view Ember.TextArea valueBinding="full_description" class="form-control" rows="6"}}
<hr>
<button {{action saveDescription}} class="btn btn-success">Save</button>
<span class="glyphicon glyphicon-info-sign"></span> More on Markdown
{{else}}
{{#if full_description}}
{{markdown full_description}}
{{else}}
<span class="text-muted">no description provided</span>
{{/if}}
{{/if}}
</p>
</div>
</div>
<div class="row page-header-title" >
<div class="col col-lg-11">
<h4>
Mentor
</h4>
</div>
<div class="col col-lg-1">
<h4 class="glyphicon glyphicon-pencil edit-button"></h4>
</div>
</div>
{{#if mentor}}
<address>
{{log mentor}}
<strong> {{mentor.employee_preferred_name}}</strong>
<br>
{{#if mentor.phone}}
<abbr title="Phone">P:</abbr> {{mentor.phone}} <br>
{{else}}
<small> no phone number provided </small> <br>
{{/if}}
{{#if mentor.email}}
<abbr title="Email">E:</abbr> {{mentor.email}}
{{else}}
<small> no email number provided </small> <br>
{{/if}}
</address>
{{/if}}
</div>
Category.hbs
<div class="col col-lg-3 menu2">
<ul style="">
<li class="menu2-header">
<button style="background:#5E9EF3;border:none" class="btn btn-sm btn-primary">New</button>
</li>
{{#each badge in badges}}
{{#link-to "badge" badge tagName="li"}}
<h6 style="">
{{badge.type}}
</h6>
<h4 style="">
<strong>{{badge.title}}</strong>
</h4>
<p>
{{badge.short_description}}
</p>
{{/link-to}}
{{else}}
<p class="lead text-center" style="margin-top:2em">
No Badges in {{label}}
</p>
{{/each}}
</ul>
</div>
<div class="col col-lg-7">
{{outlet}}
</div>
Categories.hbs
<div class="col col-lg-2 menu1">
<ul>
{{#each category in model}}
{{#if category.parent}}
{{else}}
<li class="menu1-header" > {{category.label}} </li>
{{#if category.children}}
{{#each child in category.children}}
{{#link-to 'category' child tagName="li"}}
{{child.label}}
{{/link-to}}
{{/each}}
{{/if}}
{{/if}}
{{/each}}
</ul>
</div>
{{outlet}}
Let me know if you need any other information. Any help would be greatly appreciated.

I've run into this a time or two in the past and it's almost always been due to wrapping some handlebars directive in regular html comments. Something like:
<!--
{{#if something}}hey!{{else}}ho!{{/if}}
-->

I ended up rebuilding the badgeBasic.hbs file and it turns out there were unmatched html tags. I do not know why this fixed it but it did.

Related

How to perform event bubbling in meteor template helper

I'm trying to capture data of the whole {{#each categories}} but my button .toggle-addToSet I use to do that is not capturing all the way to the top, it's only capturing data for {{#each set}} which is within {{#each categories}} unfortunately the data I need is not in there, therefore I need a way to capture data beyond {{#each set}} all the way to {{#each categories}}
this is what it looks like in the HTML
<ul>
{{#each categories}}
<li class="myIdd">
<div class="row col s12 m7">
<div class="card" id="cardId">
<div class="card-image waves-effect waves-block waves-light">
<img src="{{better_featured_image.source_url}}">
</div>
<div class="card-content">
<h5 class=" truncate grey-text text-darken-4">{{title.rendered}}</h5>
MORE <i class="waves-effect waves-teal small material-icons right">playlist_add</i>{{>
likePartial}}{{> reblogPartial}}
<!-- The modal below is what brings up all the sets the user has created so that the user can pick with set they wat to save the article in -->
<div id="modal2" class="modal bottom-sheet">
<div class="modal-content">
<div class="row">
<!-- data being captured is only below this, but i need it to capture up until li class ="myIdd" -->
{{#each set}}
<div class="col s6 m6 addSet teal">
<div class="card ">
<div class="card-image">
<span class="card-title cardSet">{{name}}</span>
</div>
<div class="card-footer">
<!-- This button is what i'm using to try and capture the data all the way to li class ="myIdd" -->
<button type="button" class="btn toggle-addToSet" name="button" data-setid="{{s._id}}">add Article Id to this Set!</button>
</div>
</div>
</div>
{{/each}}
<!-- end of capture -->
</div>
</div>
</div>
</div>
</div>
</div>
</li>
{{/each}}
</ul>
In my template helper, it's like this
Template.summeryArticle.events({
'click .toggle-addToSet': function(e, template) {
var ob = this
console.log(ob);
}
});
where var ob = this is only capturing
{{#each set}}
<div class="col s6 m6 addSet teal">
<div class="card ">
<div class="card-image">
<span class="card-title cardSet">{{name}}</span>
</div>
<div class="card-footer">
<!-- This button is what I'm using to try and capture the data all the way to li class ="myIdd" -->
<button type="button" class="btn toggle-addToSet" name="button" data-setid="{{s._id}}">add Article Id to this Set!</button>
</div>
</div>
</div>
{{/each}}
But as discussed, I need it to capture the whole document i.e
{{#each categories}}
capture everything in here
{{/each}}
When you're calling {{#each set}}...{{/each}} you're changing the context of inner block.
I'm suggesting to use {{#each catSet in set}}...{{/each}} this won't change the context of the each block, but will introduce new catSet variable, as described here
In your case:
<ul>
{{#each categories}}
<li class="myIdd">
<div class="row col s12 m7">
<div class="card" id="cardId">
<div class="card-image waves-effect waves-block waves-light">
<img src="{{better_featured_image.source_url}}">
</div>
<div class="card-content">
<h5 class=" truncate grey-text text-darken-4">{{title.rendered}}</h5>
MORE <i class="waves-effect waves-teal small material-icons right">playlist_add</i>{{>
likePartial}}{{> reblogPartial}}
<!-- The modal below is what brings up all the sets the user has created so that the user can pick with set they wat to save the article in -->
<div id="modal2" class="modal bottom-sheet">
<div class="modal-content">
<div class="row">
<!-- data being captured is only below this, but i need it to capture up until li class ="myIdd" -->
{{#each catSet in set}}
<div class="col s6 m6 addSet teal">
<div class="card ">
<div class="card-image">
<span class="card-title cardSet">{{catSet.name}}</span>
</div>
<div class="card-footer">
<!-- This button is what i'm using to try and capture the data all the way to li class ="myIdd" -->
<button type="button" class="btn toggle-addToSet" name="button" data-setid="{{s._id}}">add Article Id to this Set!</button>
</div>
</div>
</div>
{{/each}}
<!-- end of capture -->
</div>
</div>
</div>
</div>
</div>
</div>
</li>
{{/each}}
</ul>

Meteor + Iron-Router: Template no more working

I'm working on a project, it was working normally. But then I had to add Iron-Router to add some features and one of my templates do not work anymore.
I have this home.html file, that import two templates, "nova" and "piadas". But only the "nova" is displayed. How do I fix it?
home.html:
<template name="home">
<br>
{{> nova}}
<div class="fixed-action-btn horizontal">
<a class="btn-floating btn-large green accent-4"> <i class="large material-icons">person</i> </a>
<ul>
<li><a class="btn-floating green accent-4"><i class="material-icons">add</i></a></li>
<li><a class="btn-floating green accent-4"><i class="material-icons">account_circle</i></a></li>
</ul>
</div>
<br>
{{> piadas}}
</template>
piadas.html:
<template name="piadas">
<div class="row"> {{#each piadas}}
<div class="col s12 m6">
<div class="card grey lighten-4">
<div class="card-content black-text"> <span class="card-title">{{titulo}}</span>
<p class="truncate">{{piada}}</p>
</div>
<div class="card-reveal"> <span class="card-title grey-text text-darken-4">{{titulo}}<i class="material-icons right">close</i></span>
<p>Essa piada foi enviada por <strong>{{autor}}</strong> no dia <strong>{{formataData}}</strong>.</p>
<button id="btn-like" class="btn" style="float: left;"><i class="material-icons ">thumb_up</i></button>
<button id="btn-denunciar" class="btn btn-danger" style="float: right;"><i class="material-icons ">flag</i></button>
</div>
<div class="card-action"> <i class="material-icons right">more_vert</i> </div>
</div>
</div> {{/each}} </div>
</template>
I've discovered that: how the "piadas" template was returning a helper function with some MongoDB querys, I had to pass the querys for the router.

Dynamic ng-repeat using ui param value

I would like to do something like ng-repeat="statement in {{ range }}Statements" where range is a ui param value that can be pos, neu and neg depending on the URL:
/#/sidemenu-statements/1/pos
/#/sidemenu-statements/1/neg
/#/sidemenu-statements/1/neu
It would allow me to consolidate the three lists below... is it possible to do this?
If not what would be a better approach?
statements.view.html
<div ng-controller="StatementsController">
<!-- List of positive statements -->
<div class="list card" ng-repeat="statement in posStatements | orderBy: '-timestamp'" ng-if="range==='pos'">
<div class="item item-icon-left">
<i class="icon {{ statement.accountIcon }}"></i>
<h2>{{ statement.accountTag }}</h2>
<span am-time-ago="{{ statement.timestamp }}"></span>
</div>
<div class="item item-body">
<span>{{ statement.statement }}</span>
<div align="center"><p>We've assessed this post as <strong>{{ range }}</strong>. What do you think?</p></div>
</div>
<div class="button-bar">
<a class="button button-balanced"><i class="icon ion-happy"></i></a>
<a class="button button-dark">Skip</a>
<a class="button button-assertive"><i class="icon ion-sad"></i></a>
</div>
</div>
<!-- List of neutral statements -->
<div class="list card" ng-repeat="statement in negStatements | orderBy: '-timestamp'" ng-if="range==='neu'">
<div class="item item-icon-left">
<i class="icon {{ statement.accountIcon }}"></i>
<h2>{{ statement.accountTag }}</h2>
<span am-time-ago="{{ statement.timestamp }}"></span>
</div>
<div class="item item-body">
<span>{{ statement.statement }}</span>
<div align="center"><p>We've assessed this post as <strong>{{ range }}</strong>. What do you think?</p></div>
</div>
<div class="button-bar">
<a class="button button-balanced"><i class="icon ion-happy"></i></a>
<a class="button button-dark">Skip</a>
<a class="button button-assertive"><i class="icon ion-sad"></i></a>
</div>
</div>
<!-- List of negative statements -->
<div class="list card" ng-repeat="statement in negStatements | orderBy: '-timestamp'" ng-if="range==='neg'">
<div class="item item-icon-left">
<i class="icon {{ statement.accountIcon }}"></i>
<h2>{{ statement.accountTag }}</h2>
<span am-time-ago="{{ statement.timestamp }}"></span>
</div>
<div class="item item-body">
<span>{{ statement.statement }}</span>
<div align="center"><p>We've assessed this post as <strong>{{ range }}</strong>. What do you think?</p></div>
</div>
<div class="button-bar">
<a class="button button-balanced"><i class="icon ion-happy"></i></a>
<a class="button button-dark">Skip</a>
<a class="button button-assertive"><i class="icon ion-sad"></i></a>
</div>
</div>
<div>
I would do the following:
ng-repeat="statement in getStatements(range)"
and add this function in the controller (you can use a switch/case structure if you're not a fan of the string concatenation):
$scope.getStatements = function(range) {
return $scope[range + "Statements"];
};

EmberJS Rendering Delay

I have a print button that am using an {{#if}} conditional to show when a box gets expanded. I want the box to be expanded and then show the print icon at the foot of the box. But for some reason it is getting rendered early and shown in line with the collapsed box then put in the right place once the box is fully expanded. Here is my code:
Print Icon Template:
{{#if view.showPrintButton}}
<div class="print pull-right">
Print Discussion<i class="fa fa-print"></i>
</div>
{{/if}}
Box template:
{{#if permissions.comment}}
<div {{bindAttr class="controller.audienceIsShared:shared view.commentEditorExpanded:expanded :createComment"}}>
<div class="author-image-container content">
<img src="{{unbound Informal.Registry.user.pictureUrl}}" class="author-image pull-left" />
</div>
{{#if view.commentEditorExpanded}}
<div class="comment-editor-container content">
<div class="boxSizingDefault text">
{{
view view.commentEditorClass
disabledBinding="view.commentFormDisabled"
viewName="commentEditor"
valueBinding="controller.commentInProgress.initialBody"
attachmentsBinding="controller.commentInProgress.attachments"
}}
</div>
{{#if controller.audienceIsShared}}
<div class="contextualMessage">This comment will be seen across business units</div>
{{/if}}
</div>
{{#if notificationRecipients.length}}
<div class="notificationRecipients small detail">
<span>These subscribers will be notified of your comment:</span>
{{#if notificationRecipientsIsExpandable}}
{{#if view.notificationRecipientsExpanded}}
{{#with sortedNotificationRecipients}}{{> initials}}{{/with}}
{{else}}
{{#with collapsedNotificationRecipients}}{{> initials}}{{/with}}
<span class="link" {{action "expandNotificationRecipients" target="view"}}>
, {{collapsedNotificationRecipientsRemainingCount}} more...
</span>
{{/if}}
{{else}}
{{#with sortedNotificationRecipients}}{{> initials}}{{/with}}
{{/if}}
</div>
{{/if}}
View:
showPrintButton: function () {
return (this.get("expanded") !== false) && !this.get("editorExpanded");
} .property("expanded", "editorExpanded")
Thanks!

Button click event handling in Backbone/Handlebars/Bootstrap setup

I have just inherited a project that uses the three frameworks mentioned above. Here's a snippet of my template:
<div class="content-header">
<div class="content-header-title">move money to</div>
<div class="content-header-controls">
<dl>
<dd>
<a id="aMoveMoneyCancel">back</a>
</dd>
</dl>
</div>
</div>
<div class="content-edge">
<ul class="triangle-breadcrumb margin-bottom">
<li class="active"><a>DETAILS</a></li>
<li><a>REVIEW</a></li>
<li><a>DONE</a></li>
</ul>
<div class="content-section">
<div class="content-section-header">
<div class="section-title">
move money to...
</div>
</div>
<div class="content-section-body padding">
<form id="moveMoneyToForm">
<input type="hidden" name="moveMoneyToPayeeDocument.FromAccount"
value="{{moveMoneyToPayeeDocument.FromAccount}}" class="required"/>
<div class="accounts">
<div class="planted-stop"> </div>
<div class="sub-section major from-account">
<div class="sub-section-account-header">from account</div>
<div class="sub-section-account-body">
<div id="fromCarouselContainer" class="from-account">
<!--carousel slide generated dynamically-->
<!--moveMoneyTo.accountsCarousel.template-->
</div>
</div>
</div>
<!--<input type="hidden" name="moveMoneyToPayeeDocument.ToAccount" value="{{moveMoneyToPayeeDocument.ToAccount}}" />-->
<div id="toAccountContainer" class="to-account">
{{#if isIrdPayment}}
{{> app_templates_irdPayment.carouselDetail.template}}
{{else}}
{{> app_templates_moveMoneyTo.toAccount.template}}
{{/if}}
</div>
<div class="planted-stop"> </div>
<span class="stretch"></span>
</div>
<div class="sub-sections-container">
<div class="sub-sections-shield"></div>
{{#if isIrdPayment}}
{{> app_templates_irdPayment.amountDescription.template}}
{{else}}
{{#with moveMoneyToPayeeDocument}}
<div class="sub-section major">
<div class="sub-section-header">AMOUNT</div>
<div class="sub-section-body">
<input id="amount" name="moveMoneyToPayeeDocument.Amount"
type="text" step="0.01"
placeholder="Amount" value="{{unformatCurrency Amount}}"
class="required number amount-input"/>
</div>
</div>
<div class="sub-section major">
<div class="sub-section-header">Description</div>
<div class="sub-section-body" id="divDescriptionContainer">
{{> app_templates_moveMoneyTo.description.template}}
</div>
</div>
{{/with}}
{{/if}}
{{#with moveMoneyToPayeeDocument}}
<div class="sub-section major">
<div class="scheduling">
<div class="sub-section-header">SCHEDULING</div>
<div class="sub-section-body">
<div class="transfer-date">
<div id="divTransferDate"
class="input-section move-money-to-recurring-section {{#if isRecurring}} collapse {{else}} in collapse {{/if}}"
{{#unless isRecurring}} style="height: auto;" {{/unless}}>
<div>
<label for="date">Transfer date</label>
<input id="date" class="date-input" type="text" placeholder="Date"
min="{{today this}}"
data-date-min="{{today this}}"
value="{{formatDate TransferDate 'input'}}"/>
</div>
</div>
<div class="input-section last">
<div>
<label class="checkbox">
<input id="recurringTransaction" type="checkbox"
data-target=".move-money-to-recurring-section" data-toggle="collapse"
{{#if isRecurring}} checked="checked" {{/if}}
> Recurring transaction
</label>
</div>
</div>
<div id="divSchedulingDetails" class="move-money-to-recurring-section {{#if isRecurring}} in collapse {{else}} collapse {{/if}} ">
{{#with ScheduleDetails}}
<div id="recurringSection">
{{> app_templates_moveMoneyTo.scheduling.template }}
</div>
{{/with}}
</div>
</div>
</div>
</div>
<div class="buttons-container">
<button id="next" class="btn btn-item btn-primary" disabled="disabled">NEXT</button>
<button id="cancel" class="btn btn-item btn-dark">BACK</button>
</div>
{{/with}}
</div>
</form>
</div>
</div>
</div>
In Chrome this was not working properly, only in Chrome. For some reason the URL it navigated to had a whole bunch of query parameters inserted in the middle. I assume that stuffed up the routing because it went to the view it was supposed to render, but then came back and re-rendered this form again! This is only in Chrome, I couldn't reproduce it in FF or IE9 (haven't tried other versions).
Having gone back through revision history I discovered this form used to look like this:
<div class="content-header">
<div class="content-header-title">move money to</div>
<div class="content-header-controls">
<dl>
<dd>
<a id="aMoveMoneyCancel">back</a>
</dd>
</dl>
</div>
</div>
<div class="content-edge">
<ul class="triangle-breadcrumb margin-bottom">
<li class="active"><a>DETAILS</a></li>
<li><a>REVIEW</a></li>
<li><a>DONE</a></li>
</ul>
<div class="content-section">
<div class="content-section-header">
<div class="section-title">
move money to...
</div>
</div>
<div class="content-section-body padding">
<form id="moveMoneyToForm">
<input type="hidden" name="moveMoneyToPayeeDocument.FromAccount"
value="{{moveMoneyToPayeeDocument.FromAccount}}" class="required"/>
<div class="accounts">
<div class="planted-stop"> </div>
<div class="sub-section major from-account">
<div class="sub-section-account-header">from account</div>
<div class="sub-section-account-body">
<div id="fromCarouselContainer" class="from-account">
<!--carousel slide generated dynamically-->
<!--moveMoneyTo.accountsCarousel.template-->
</div>
</div>
</div>
<!--<input type="hidden" name="moveMoneyToPayeeDocument.ToAccount" value="{{moveMoneyToPayeeDocument.ToAccount}}" />-->
<div id="toAccountContainer" class="to-account">
{{#if isIrdPayment}}
{{> app_templates_irdPayment.carouselDetail.template}}
{{else}}
{{> app_templates_moveMoneyTo.toAccount.template}}
{{/if}}
</div>
<div class="planted-stop"> </div>
<span class="stretch"></span>
</div>
<div class="sub-sections-container">
<div class="sub-sections-shield"></div>
{{#if isIrdPayment}}
{{> app_templates_irdPayment.amountDescription.template}}
{{else}}
{{#with moveMoneyToPayeeDocument}}
<div class="sub-section major">
<div class="sub-section-header">AMOUNT</div>
<div class="sub-section-body">
<input id="amount" name="moveMoneyToPayeeDocument.Amount"
type="text" step="0.01"
placeholder="Amount" value="{{unformatCurrency Amount}}"
class="required number amount-input"/>
</div>
</div>
<div class="sub-section major">
<div class="sub-section-header">Description</div>
<div class="sub-section-body" id="divDescriptionContainer">
{{> app_templates_moveMoneyTo.description.template}}
</div>
</div>
{{/with}}
{{/if}}
{{#with moveMoneyToPayeeDocument}}
<div class="sub-section major">
<div class="sub-section-header">SCHEDULING</div>
<div class="sub-section-body">
<div class="transfer-date">
<div id="divTransferDate"
class="input-section move-money-to-recurring-section {{#if isRecurring}} collapse {{else}} in collapse {{/if}}"
{{#unless isRecurring}} style="height: auto;" {{/unless}}>
<div>
<label for="date">Transfer date</label>
<input id="date" class="date-input" type="text" placeholder="Date"
min="{{today this}}"
data-date-min="{{today this}}"
value="{{formatDate TransferDate 'input'}}"/>
</div>
</div>
<div class="input-section last">
<div>
<label class="checkbox">
<input id="recurringTransaction" type="checkbox"
data-target=".move-money-to-recurring-section" data-toggle="collapse"
{{#if isRecurring}} checked="checked" {{/if}}
> Recurring transaction
</label>
</div>
</div>
<div id="divSchedulingDetails" class="move-money-to-recurring-section {{#if isRecurring}} in collapse {{else}} collapse {{/if}} ">
{{#with ScheduleDetails}}
<div id="recurringSection">
{{> app_templates_moveMoneyTo.scheduling.template }}
</div>
{{/with}}
</div>
</div>
</div>
{{/with}}
</div>
</form>
</div>
<div class="buttons-container">
<button id="next" class="btn btn-item btn-primary" disabled="disabled">NEXT</button>
<button id="cancel" class="btn btn-item btn-dark">BACK</button>
</div>
</div>
</div>
The difference being the location of the buttons were located outside the form and {{with}} blocks. The Backbone view has
'click #next': 'onNext'
I assume this is the click event handler binding? It seems to be bound by id, which I understand means it should not matter where the button lives. Unless... one of the bootstrap classes has specific meaning, and acts as a form submit?
I am new to the Backbone/Handlebars/Bootstrap combo, so I hope I have explained myself reasonably well.
The buttons are inside the form element, quick guess is they are submitting the form!
Add button type as follows :
<button type='button'>
Reference :
https://stackoverflow.com/a/9315482/566092

Categories

Resources