HandleBars Compile w/ RequireJS and BackboneJS - backbone.js

requirejs configuration:
require.config({
baseUrl: '/js/',
paths: {
jquery: './libs/jquery/jquery-1.10.1.min',
underscore: './libs/underscore/underscore-min',
backbone: './libs/backbone/backbone-min',
handlebars: './libs/handlebars/handlebars',
templates: '/templates'
},
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ['jquery', 'underscore'],
exports: 'Backbone'
}
}
});
View:
define([
'backbone',
'handlebars',
'text!templates/mytemplate.html'
], function(Backbone, Handlebars, Template){
MyView = Backbone.View.extend({
tagName: 'li',
template: Handlebars.compile(Template),
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
return MyView;
});
I encountered the following error:
Uncaught TypeError: Cannot call method 'compile' of undefined.

add this to your shim configuration:
shim: {
handlebars: {
exports: 'Handlebars'
},

Related

Cannot load nested views' controllers with ocLazyload and ui-router

I have the code below:
.state('shops', {
abstract: true,
url: "/shops/:shopid",
data: {
pageTitle: 'Shop Settings'
},
views: {
'content#': {
templateUrl: "views/shops.html",
}
},
resolve: {
deps: ['$ocLazyLoad', function($ocLazyLoad) {
return $ocLazyLoad.load({
name: 'MetronicApp',
insertBefore: '#ng_load_plugins_before',
files: [
'js/controllers/ShopDetailController.js',
'css/views/ngTable.css',
]
});
}]
}
})
.state('shops.feedbacks', {
url: "/feedbacks",
data: {
pageTitle: 'Feedbacks',
requireLogin: true
},
ncyBreadcrumb: {
label: 'Feedback Management'
},
views: {
'detail': {
templateUrl: "views/feedbacks.list.html",
controller: "FeedbackController"
}
},
resolve: {
deps: ['$ocLazyLoad', function($ocLazyLoad) {
return $ocLazyLoad.load({
name: 'MetronicApp',
insertBefore: '#ng_load_plugins_before',
files: [
'js/controllers/FeedbackController.js',
]
});
}]
}
})
and the configuration is:
MetronicApp.config(['$ocLazyLoadProvider', function($ocLazyLoadProvider) {
$ocLazyLoadProvider.config({
debug: true
});
}]);
I am getting the error:
Error: [ng:areq] Argument 'FeedbackController' is not a function, got undefined
What did I do wrong? I also tried to inject FeedbackController in the parent state but it also doesn't work. Any idea?

Backbone templates doesn't update to new value

I scaffolded a backbone app with Yeoman. I used the standard template .ejs. There is something strange happening. If I take an element form my HTML it will update to the standard .ejs `your content here
When I edit my template however and reload, the new content will not be shown, and the old content is showed:
<p>your content here </p>
My code:
main.js
/*global require*/
'use strict';
require.config({
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: [
'underscore',
'jquery'
],
exports: 'Backbone'
},
bootstrap: {
deps: ['jquery'],
exports: 'jquery'
}
},
paths: {
jquery: '../bower_components/jquery/dist/jquery',
backbone: '../bower_components/backbone/backbone',
underscore: '../bower_components/underscore/underscore',
bootstrap: '../bower_components/sass-bootstrap/dist/js/bootstrap'
}
});
require([
'backbone',
'routes/app'
], function (Backbone, AppRouter) {
var app = new AppRouter();
Backbone.history.start();
});
AppRouter (App.js);
/*global define*/
define([
'jquery',
'backbone',
'views/wine',
'views/headerView'
], function ($, Backbone, WineView, HeaderView) {
'use strict';
var AppRouter = Backbone.Router.extend({
routes: {
'' : 'doSomething'
},
doSomething: function() {
console.log('doSomething init');
var headerView = new HeaderView();
}
});
return AppRouter;
});
And the HeaderView:
/*global define*/
define([
'jquery',
'underscore',
'backbone',
'templates'
], function ($, _, Backbone, JST) {
'use strict';
var HeaderViewView = Backbone.View.extend({
template: JST['app/scripts/templates/HeaderView.ejs'],
tagName: 'div',
id: '',
className: '',
events: {
'click .new' : 'addNew'
},
initialize: function () {
this.render();
},
render: function () {
$('#header').append(this.template);
}
});
return HeaderViewView;
});
HeaderView.ejs
<h1>New Text</h1>
Output website:
your content here

Reqiurejs and Backbone - Collection fetch

When I manually define my collection content, everything works. But after I try to fetch data from server(I get valid response), my View is not showing. Collection View (ul) is showing, but single views (li) are not ? Is there something I need to watch when fetching data to collection ?
UPDATE
main.js
require.config({
paths: {
"jquery":"vendor/jquery/jquery",
"underscore":"vendor/underscore-amd/underscore",
"backbone":"vendor/backbone-amd/backbone",
"text":"../vendor/requirejs/text",
"mustache": "../vendor/mustache/mustache"
},
shim: {
underscore: {
exports: "_"
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
}
});
require([
'app',
], function(App){
// The "app" dependency is passed in as "App"
App.initialize();
});
app.js
define([
'jquery',
'underscore',
'backbone',
'collections/ObjaveCollection',
'views/ObjaveView'
], function($, _, Backbone,ObjaveCollection,ObjaveView){
var initialize = function(){
var objave = new ObjaveCollection();
objave.fetch();
var objaveView = new ObjaveView({ collection: objave});
$(document.body).append(objaveView.render().el);
}
return {
initialize : initialize
};
});
ObjavaModel.js
define([
'jquery',
'underscore',
'backbone'
], function($, _, Backbone){
var ObjavaModel = Backbone.Model.extend({
defaults:{
naslov: 'My service',
cijena: 100,
}
});
return ObjavaModel;
});
ObjaveCollection.js
define([
'jquery',
'underscore',
'backbone',
'models/ObjavaModel'
], function($, _,Backbone,ObjavaModel){
var ObjaveCollection = Backbone.Collection.extend({
model: ObjavaModel
});
return ObjaveCollection;
});
ObjavaView.js
define([
'jquery',
'underscore',
'backbone',
'text!templates/objavaTemplate.html',
'mustache',
], function($, _, Backbone,objavaTemplate,Mustache){
var ObjavaView = Backbone.View.extend({
tagName: "li",
initialize: function () {
this.template = objavaTemplate;
},
render: function() {
rendered = Mustache.to_html(this.template, this.model.toJSON());
$(this.el).html(rendered);
return this;
}
});
return ObjavaView;
});
ObjaveView.js
define([
'jquery',
'underscore',
'backbone',
'views/ObjavaView'
], function($, _, Backbone,ObjavaView){
var ObjaveView = Backbone.View.extend({
tagName: 'ul',
render: function() {
this.collection.each(function(item) {
console.log(item);
var objavaView = new ObjavaView({ model: item });
console.log(this.$el);
this.$el.append(objavaView.render().el);
}, this);
return this;
}
});
return ObjaveView;
});
Are you rerendering your view after the data has been fetched? For example, in your view (ObjaveView.js) add:
initialize: function () {
this.listenTo(this.collection, "sync", this.render);
}

extjs - Store with autoload true should not load on application launch

I have a grid linked to a store with autoLoad: true. The problem is that the store gets loaded on application launch, even if the view is created only later when accessed through a menu.
I have referenced the store in Application.js and in the view, but I'm not instatiating explicitly neither the store nor the view.
I don't know how to achieve that the store is loaded only when needed by the view.
If I set autoLoad: true, the store gets loaded on application launch.
If I set autoLoad: false, the store doesn't get loaded at all.
I know this is pretty basic, but I'm stuck so far.
Here is all the relevant code for reference:
app/store/Owners.js
Ext.define('Mb.store.Owners', {
extend: 'Ext.data.Store',
model: 'Mb.model.Owner',
autoLoad: true,
proxy: {
...
});
Application.js
Ext.define('Mb.Application', {
name: 'Mb',
extend: 'Ext.app.Application',
models: [
'Owner'
],
stores: [
'Owners'
],
...
app/view/Owners.js
Ext.define('Mb.view.winbiz.Owners', {
extend: 'Ext.grid.Panel',
alias: 'widget.test-gridPanel',
store: 'winbiz.Owners',
columns: [{
...
The view is instantiated in the controller:
Ext.define('Mb.controller.Winbiz', {
extend: 'Ext.app.Controller',
views: [
'Owners'
],
init: function(){
this.control({
'menu #test': {click: this.onMenuTest},
})
},
onMenuTest: function(){
this.getController('Main').addToMainTab('test-gridPanel');
},
You can add render handler to view which will call store load method and disable autoLoad.
Example listener:
Ext.define('Mb.view.winbiz.Owners', {
extend: 'Ext.grid.Panel',
[...],
initComponent: function(){
this.callParent();
this.on('render', this.loadStore, this);
},
loadStore: function() {
this.getStore().load();
}
});
I would let the view's controller handle the store load.
Start by disabling autoload on the store.
Ext.define('Mb.controller.Winbiz', {
extend: 'Ext.app.Controller',
views: [
'Owners'
],
ownerStore: null,
init: function(){
this.control({
'menu #test': {click: this.onMenuTest},
});
this.ownerStore = Ext.getStore('winbiz.Owners');
},
onMenuTest: function() {
if (this.ownerStore.loaded === false) {
this.ownerStore.load(
scope: this,
callback: this.onOwnerStoreLoaded
);
}
else {
this.addToTab();
}
},
onOwnerStoreLoaded: function (store, records, successful, eOpts) {
if (successful) {
store.loaded = true;
this.addToTab();
}
},
addToTab: function () {
this.getController('Main').addToMainTab('test-gridPanel');
}
Wheter you want to change the view before or after the store is loaded is another question.
This is my final controller code:
Ext.define('Mb.controller.Winbiz', {
extend: 'Ext.app.Controller',
views: [
'Owners'
],
refs: [{ref: 'testGrid', selector: 'test-gridPanel'}],
init: function(){
this.listen({
store: {
'#Owners':{ load: this.onOwnersLoad}
}
})
this.control({
'menu #test': {click: this.onMenuTest},
'test-gridPanel': {render: this.onOwnersRender}
})
},
onMenuTest: function(){
this.getController('Main').addToMainTab('test-gridPanel');
},
onOwnersLoad: function(store){
store.loaded = true
},
onOwnersRender: function(){
var store = this.getTestGrid().getStore();
if(!store.loaded)store.load();
},
It puts all code into the controller as suggested by #pcguru and uses the render event to shorten the code as suggested by #Lolo. Thanks

relative paths using extjs 4

My directory structure looks like follows. (i'm using ext mvc )
www.mysite.com/ext/designer.js
www.mysite.com/ext/app/view
www.mysite.com/ext/app/store
I have the js declared here
<script type="text/javascript" src="http://extjs.cachefly.net/ext-4.0.2a/ext-all-debug.js"></script>
<script type="text/javascript" src="/ext/designer.js"></script>
my issue is that when it calls the store the path is incorrect. "/Jobs/edit/" is the page that contains the js
https://www.mysite.com/Jobs/edit/app/store/JobTypes.js?_dc=1326712425128
So how can i use extjs ( in my existing web application ) so that it will use the correct paths.
here is designer js
Ext.Loader.setConfig({
enabled: true
});
Ext.application({
name: 'MyApp',
stores: [
'JobTypes',
'SalesContact',
'Job',
'AccountHandlers'
],
launch: function() {
Ext.QuickTips.init();
var cmp1 = Ext.create('MyApp.view.Jobs', {
renderTo: Ext.getBody()
});
cmp1.show();
}
});
I've tried the following after the config but it doesn't seem to override the path.
Ext.Loader.setPath('MyApp', '/Ext/App');
so you can set the app folder like so .
appFolder: '/ext/app',
Ext.application({
name: 'MyApp',
appFolder: '/ext/app',
stores: [
'JobTypes',
'SalesContact',
'Job',
'AccountHandlers'
],
launch: function() {
Ext.QuickTips.init();
Ext.Loader.setPath('MyApp', '/Ext/App');
var cmp1 = Ext.create('MyApp.view.Jobs', {
renderTo: Ext.getBody()
});
cmp1.show();
}
});

Resources