Error with include router in underscore backbone - backbone.js

Trying to use underscore in project with backbone, but receive an error:
Uncaught TypeError: undefined is not a function
In my view, because variable Router undefined. I am new one in backbone and underscore, so please help me, maby something need to change in my code.
main.js
require.config({
paths: {
jquery: 'lib/jquery-2.1.1',
underscore: 'lib/underscore',
backbone: 'lib/backbone',
view: 'view/view'
},
shim: {
'backbone': {
deps: ['jquery','underscore'],
exports: 'Backbone'
}
}
});
require([
'app'
], function(App){
App.initialize();
});
app.js
define([
'router' // Request router.js
], function(Router) {
var initialize = function() {
Router.initialize();
};
return {
initialize: initialize
};
});
router.js
define([
'backbone',
'model/model',
'view'
], function(Backbone, appState) {
var router = Backbone.Router.extend({
routes: {
"": "selected_currency",
"!/": "selected_currency",
"!/finish": "finish"
},
selected_currency: function() {
appState.set({state: "selected_currency"});
},
finish: function () {
appState.set({state: "finish"});
}
});
Backbone.history.start();
return router;
});
/model/model.js
define([
'underscore',
'backbone'
], function(_, Backbone) {
var AppState = Backbone.Model.extend({
defaults: {
currencies: ['USD', 'EUR'],
selected_currency: '',
state: "selected_currency"
},
url: '/site/create-account'
});
return new AppState();
});
view/view.js
define([
'jquery',
'underscore',
'backbone',
'router', // Request router.js
'model/model'
], function($, _, Backbone, Router, appState) {
var Block = Backbone.View.extend({
el: $("#block"),
templates: {
"selected_currency": _.template($('#step_1').html()),
"finish": _.template($('#step_1_complete').html() + $('#step_2').html())
},
events: {
"click button": "get_currency"
},
initialize: function() {
this.model.bind('change', this.render, this);
},
get_currency: function() {
var currency = this.$el.find("[name=currency]").val();
appState.set({selected_currency: currency});
appState.fetch({
data: {'currency': appState.get('selected_currency')},
type: 'POST'
});
appState.once('sync error', function(model) {
this.model.set({"state": "finish"});
}, this);
},
render: function() {
var state = this.model.get("state");
$(this.el).html(this.templates[state](this.model.toJSON()));
return this;
}
});
new Block({model: appState});
var router = new Router();
appState.trigger("change");
appState.bind("change:state", function() {
var state = this.get("state");
if (state == "selected_currency")
router.navigate("!/", false);
else
router.navigate("!/" + state, false);
});
});

Related

Webix 4.3 module not loading in Angularjs

I have an issue with the new Webix 4.3 release:
angular.js:66 Uncaught Error: [$injector:modulerr] Failed to instantiate
module monitorApp due to:
Error: [$injector:modulerr] Failed to instantiate module webix due to:
Error: [$injector:nomod] Module 'webix' is not available! You either
misspelled the module name or forgot to load it. If registering a module
ensure that you specify the dependencies as the second argument.
I get this error just updating the version from 4.2, here is how do i inject the module:
var app=angular.module("monitorApp", ['webix', 'ngRoute','ui.router']);
html:
<!--Includes-->
<script src="Scripts/angular.js"></script>
<script src="Scripts/webix.js"></script>
Any ideas about what is it going?
Starting from Webix 4.3, AngularJs integration is a separate module
https://docs.webix.com/desktop__whats_new_4_3.html
You can grab it from github
https://github.com/webix-hub/webix-angular
Or install through npm
npm install webix-angular
You can add an extra file which is mandatory for the Webix Angular Integration part.
// Code goes here
if (window.angular)
(function(){
function id_helper($element){
//we need uniq id as reference
var id = $element.attr("id");
if (!id){
id = webix.uid();
$element.attr("id", id);
}
return id;
}
function locate_view_id($element){
if (typeof $element.attr("webix-ui") != "undefined")
return $element.attr("id");
return locate_view_id($element.parent());
}
//creates webix ui components
angular.module("webix", [])
.directive('webixUi', [ "$parse", function($parse) {
return {
restrict: 'A',
scope: false,
link:function ($scope, $element, $attrs, $controller){
var dataname = $attrs["webixUi"];
var callback = $attrs["webixReady"];
var watch = $attrs["webixWatch"];
var wxRoot = null;
var id = id_helper($element);
$element.ready(function(){
if (wxRoot) return;
if (callback)
callback = $parse(callback);
//destruct components
$element.bind('$destroy', function() {
if (wxRoot && !wxRoot.$destructed && wxRoot.destructor)
wxRoot.destructor();
});
//ensure that ui is destroyed on scope destruction
$scope.$on('$destroy', function(){
if (wxRoot && !wxRoot.$destructed && wxRoot.destructor)
wxRoot.destructor();
});
//webix-ui attribute has some value - will try to use it as configuration
if (dataname){
//configuration
var watcher = function(data){
if (wxRoot) wxRoot.destructor();
if ($scope[dataname]){
var config = webix.copy($scope[dataname]);
config.$scope =$scope;
$element[0].innerHTML = "";
wxRoot = webix.ui(config, $element[0]);
if (callback)
callback($scope, { root: wxRoot });
}
};
if (watch !== "false")
$scope.$watch(dataname, watcher);
watcher();
} else {
//if webix-ui is empty - init inner content as webix markup
if (!$attrs["view"])
$element.attr("view", "rows");
var ui = webix.markup;
var tmp_a = ui.attribute; ui.attribute = "";
//FIXME - memory leaking, need to detect the moment of dom element removing and destroy UI
if (typeof $attrs["webixRefresh"] != "undefined")
wxRoot = ui.init($element[0], $element[0], $scope);
else
wxRoot = ui.init($element[0], null, $scope);
ui.attribute = tmp_a;
if (callback)
callback($scope, { root: wxRoot });
}
//size of ui
$scope.$watch(function() {
return $element[0].offsetWidth + "." + $element[0].offsetHeight;
}, function() {
if (wxRoot) wxRoot.adjust();
});
});
}
};
}])
.directive('webixShow', [ "$parse", function($parse) {
return {
restrict: 'A',
scope: false,
link:function ($scope, $element, $attrs, $controller){
var attr = $parse($attrs["webixShow"]);
var id = id_helper($element);
if (!attr($scope))
$element.attr("hidden", "true");
$scope.$watch($attrs["webixShow"], function(){
var view = webix.$$(id);
if (view){
if (attr($scope)){
webix.$$(id).show();
$element[0].removeAttribute("hidden");
} else
webix.$$(id).hide();
}
});
}
};
}])
.directive('webixEvent', [ "$parse", function($parse) {
var wrap_helper = function($scope, view, eventobj){
var ev = eventobj.split("=");
var action = $parse(ev[1]);
var name = ev[0].trim();
view.attachEvent(name, function(){
return action($scope, { id:arguments[0], details:arguments });
});
};
return {
restrict: 'A',
scope: false,
link:function ($scope, $element, $attrs, $controller){
var events = $attrs["webixEvent"].split(";");
var id = id_helper($element);
setTimeout(function(){
var first = $element[0].firstChild;
if (first && first.nodeType == 1)
id = first.getAttribute("view_id") || id;
var view = webix.$$(id);
for (var i = 0; i < events.length; i++) {
wrap_helper($scope, view, events[i]);
}
});
}
};
}])
.directive('webixElements', [ "$parse", function($parse) {
return {
restrict: 'A',
scope: false,
link:function ($scope, $element, $attrs, $controller){
var data = $attrs["webixElements"];
var id = id_helper($element);
if ($scope.$watchCollection)
$scope.$watchCollection(data, function(collection){
setTimeout(function(){
var view = webix.$$(id);
if (view){
view.define("elements", collection);
view.refresh();
}
},1);
});
}
};
}])
.directive('webixData', [ "$parse", function($parse) {
return {
restrict: 'A',
scope: false,
link:function ($scope, $element, $attrs, $controller){
var data = $attrs["webixData"];
var id = id_helper($element);
if ($scope.$watchCollection)
$scope.$watchCollection(data, function(collection){
if (collection){
setTimeout(function(){
loadData($element, id, collection, 0);
},1);
}
});
}
};
}]);
function loadData($element, id, collection, num){
if (num > 10) return;
var first = $element[0].firstChild;
if (first && first.nodeType == 1)
id = first.getAttribute("view_id") || id;
var view = webix.$$(id);
if (view){
if (view.options_setter){
view.define("options", collection);
view.refresh();
}else{
if (view.clearAll)
view.clearAll();
view.parse(collection);
}
} else {
webix.delay(loadData, this, [$element, id, collection], 100, num+1);
}
}
})();
<!doctype html>
<html lang="en" ng-app="webixApp">
<head>
<meta charset="utf-8">
<title>Webix - Angular : Layouts</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.js"></script>
<script src="https://angular-ui.github.io/ui-router/release/angular-ui-router.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.webix.com/edge/webix.css">
<script type="text/javascript" src="https://cdn.webix.com/edge/webix.js"></script>
<script type="text/javascript" src="script.js"></script>
<script type="text/javascript">
var app = angular.module('webixApp', ["webix", 'ui.router']);
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/add");
$stateProvider
.state('/add', {
url: '/add',
template: 'This is the Routed Addition File'
})
.state('/sub', {
url: '/sub',
template: 'This is the Routed Subtraction File'
})
.state('/div', {
url: '/div',
template: 'This is the Routed Division File'
})
.state('/multi', {
url: '/multi',
template: 'This is the Routed Multiplication File'
})
})
app.controller('jsonCtrl', function($scope) {
var treeData = {
data: [{
id: "root",
value: "Super Micro Flow",
open: true,
link: "add",
data: [{
id: "1",
open: true,
value: "AP1",
link: "multi",
data: [{
id: "1.1",
value: "2G09#M10000761",
link: "div",
data: [{
id: "1.11",
value: "2G09#M10000761",
link: "add",
data: [{
id: "1.11",
value: "2G09#M10000761",
link: "sub"
}, {
id: "1.12",
value: "2G09#M10855757",
link: "multi"
}, {
id: "1.13",
value: "2G09#D10PP0761",
link: "div"
}]
}, {
id: "1.12",
value: "2G09#M10855757",
link: "multi"
}, {
id: "1.13",
value: "2G09#D10PP0761",
link: "div"
}]
}, {
id: "1.2",
value: "2G09#M10855757",
link: "multi"
}, {
id: "1.3",
value: "2G09#D10PP0761",
link: "div"
}]
}, {
id: "2",
open: false,
value: "AP12",
link: "multi",
data: [{
id: "2.1",
value: "2G09#M10000761",
link: "sub"
}, {
id: "2.2",
value: "2G09#M10855757",
link: "multi"
}, {
id: "2.3",
value: "2G09#D10PP0761",
link: "div"
}]
}, {
id: "3",
open: false,
value: "EP45",
link: "div",
data: [{
id: "3.1",
value: "2G09#M10000761",
link: "sub"
}, {
id: "3.2",
value: "2G09#M10855757",
link: "multi"
}, {
id: "3.3",
value: "2G09#D10PP0761",
link: "div"
}]
}, {
id: "4",
open: false,
value: "CR7767",
link: "sub",
data: [{
id: "4.1",
value: "2G09#M10000761",
link: "sub"
}, {
id: "4.2",
value: "2G09#M10855757",
link: "multi"
}, {
id: "4.3",
value: "2G09#D10PP0761",
link: "div"
}]
}]
}]
}
$scope.myTree = {
view: "tree",
data: treeData,
template: "{common.icon()}{common.folder()}<a ui-sref='#link#' href='##link#'>#value#</a>",
}
})
</script>
</head>
<body ng-controller="jsonCtrl">
<div webix-ui type="space">
<div height="35">Welcome to Angular Webix App </div>
<div view="cols" type="wide" margin="10">
<div width="300">
<input type="text" placeholder="Type something here" ng-model="app"> Hello {{app}}!
<div webix-ui="myTree"></div>
</div>
<div view="resizer"></div>
<div view="tabview">
<div header="Angular UI Routing Example">
<div ng-controller="jsonCtrl">
<div ui-view></div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
You can copy the script file and put into your application as an independent file. Don't write anything in this file.

How to resolve for angular ui-route

Here is my angularjs code. I have created different routes but i am unable to resolve my contract.dashboard route. If i remove the route object, it works fine but when i tried to reslove something from my service, it dose not work.
(function() {
'use strict';
angular
.module('app.contracts')
.run(appRun);
var _base = {
// Contract Base Contractor
contract: {
controllerAs: 'c',
controller: ['$scope', '$state', 'ContractModel', function($scope, $state, ContractModel){
'ngInject';
var that = this;
$scope.$watch(function(){ return $state.current.data.mode; }, function() { that.mode = $state.current.data.mode; });
that.contract = new ContractModel();
}]
}
};
/* #ngInject */
function appRun(routerHelper) {
routerHelper.configureStates(getStates());
}
function getStates() {
return [
{
state: 'contract',
config: angular.extend({
abstract: true,
template: '<contract-manager><ui-view/></<contract-manager>',
url: '/contract'
}, _base.contract)
},
{
state: 'contract.new',
config: angular.extend({
url: '/new',
template: '<contract-editor mode="c.mode" contract="c.contract"></<contract-editor>',
title: 'Contract Editor',
data: {
mode: 'new'
}
}, _base.contract)
},
{
state: 'contract.dashboard',
config: angular.extend({
url: '',
template: '<contract-dashboard></contract-dashboard>',
title: 'Contract Dashboard',
data: {
mode:'dashboard'
},
resolve: {
stubs: function(stubs){
return stubs.service.registerGetCustomers();
}
}
}, _base.contract)
}
];
}
})();

Marionette add grandchild views

I'm building a photo album system with tag functionality. You can tag people in a picture within the album.
I want to build this in Backbone and am trying to set models, collections and views. The models and collections are working with backbone-relational. I managed to show a list with photos, but the problem now is showing the tags in each photo.
How should I do this?
My code so far:
require(['../../common'], function (common) {
require(
["jquery",
"underscore",
"backbone",
"backbone-relational",
"marionette",
"text!templates/phototag.tpl",
"text!templates/tag.tpl",
"pages/fotoalbum/models/album"
],
function($, _, Backbone,Br,marionette,photoTpl,tagTpl,Album) {
items = [
{
'fotonaam':'http://loremipsum.com/300/400',
'tags':
[
{name:'John Doe', 'x':0.5, 'y':0.6},
{name:'Pieter J', 'x':0.5, 'y':0.6}
]
},
{
'fotonaam':'http://loremipsum.com/300/400',
'tags':[
{name:'Hans T', 'x':0.66, 'y':0.2}
]
}
];
var album = new Album( {'photos':items } );
console.log(album);
// vieww
var TagItemView = Backbone.Marionette.ItemView.extend({
tagName: "li",
template: tagTpl
});
var PhotoItemView = Backbone.Marionette.CollectionView.extend({
tagName: "li",
template: photoTpl,
childView: TagItemView
});
var AlbumCollectionView = Backbone.Marionette.CollectionView.extend({
tagName: "ul",
className: "list",
childView: PhotoItemView
});
var myAlbumView = new AlbumCollectionView({'collection':album.get('photos')});
myAlbumView.render();
$('#photolist').append(myAlbumView.el);
});
});
The answer is in Marionette's CompositeView.
This is my new code:
require(['../../common'], function (common) {
require(
["jquery",
"underscore",
"backbone",
"backbone-relational",
"marionette",
"text!templates/phototag.tpl",
"text!templates/taglist.tpl",
"text!templates/tag.tpl",
"pages/fotoalbum/models/album"
],
function($, _, Backbone,Br,marionette,photoTpl,tagListTpl,tagTpl,Album) {
items = [
{
img:'http://loremipsum.com/300/400',
tags:
[
{name:'John Doe', x:0.5, y:0.6},
{name:'Pieter J', x:0.5, y:0.6}
]
},
{
img:'http://loremipsum.com/300/400',
tags:[
{name:'Hans T', x:0.66, y:0.2}
]
}
];
var album = new Album( {'photos':items } );
var tagCollectionView = Backbone.Marionette.CompositeView.extend({
template: tagListTpl,
tagName: "ul",
});
var PhotoCollectionView = Backbone.Marionette.CompositeView.extend({
template: photoTpl,
tagName: "li",
childViewContainer:'.info',
childView: tagCollectionView,
model:this.model,
initialize: function(){
var tags = this.model.get('tags');
this.collection = tags;
this.model = this.model
},
serializeData: function(){
return {
"name": "some value"
}
}
});
var AlbumCollectionView = Backbone.Marionette.CollectionView.extend({
tagName: "ul",
className: "list",
childView: PhotoCollectionView,
});
var myAlbumView = new AlbumCollectionView({'collection':album.get('photos')});
myAlbumView.render();
$('#photolist').append(myAlbumView.el);
});
});

Update $scope with $resource

Why is only the one that don't use $resource.get() work? I am using kendo-angular to update. Has this something to do with async? The main variable looks exactly the same so this has to have something to do with $resourse. What am I missing`
This works:
app.controller('SubjectCntrl', ['$scope', 'categoryService', function($scope, categoryService) {
var main = categoryService.getCategories();
var subjects = {
data : [main]
};
$scope.subjects = {
dataSource: subjects
};
}]);
This does not:
app.controller('SubjectCntrl', ['$scope', 'categoryService', 'ApiFactory', function($scope, categoryService, ApiFactory) {
ApiFactory.get(function(categoriesData) {
var main = categoryService.getCategories();
var subjects = {
data : [main]
};
$scope.subjects = {
dataSource: subjects
};
});
}]);
The factory:
app.factory('ApiFactory', ['$resource', function($resource) {
return $resource('http://localhost:8080/rest/forum/categories/1');
}]);
Service:
app.service('categoryService', ['$resource', function($resource){
this.getCategories = function(){
var farmingSubjects = [ {text: "Poteter", spriteCssClass: "subject"}, {text: "Agurk", spriteCssClass: "subject"} ];
var forestSubjects = [ {text: "Tall", spriteCssClass: "subject"}, {text: "Gran", spriteCssClass: "subject"} ];
var animalSubjects = [ {text: "Hundar", spriteCssClass: "subject"}, {text: "Katter", spriteCssClass: "subject"} ];
var farming = { text: "Jordbruk", items: farmingSubjects };
var forest = { text: "Skogshold", items: forestSubjects };
var animals = { text: "Dyrebruk", items: animalSubjects };
var subjects = [farming, forest, animals ];
var main = { text: "Huvudemner", expanded: true, items: subjects};
return main;
};
}]);
Edit: The success function is called without doubt.
ApiFactory.get(function(data){
console.log('success, got data: ', data);
}, function(err){
alert('request failed');
});
I think the second case is not working because you ApiFactory call is failing. The callback you have declared is for success.

Getting data with backbone .fetch from a static .json file

Not sure why this isn't working, the app loads fine. I just get the error each time the load function is called without even requesting the json file.
Ive used this same code to load data from a java controller and it works fine, not sure how the static json file is different.
The View:
define([
'jquery',
'underscore',
'backbone',
'validate',
'collections/getBusiness',
'text!templates/home/homeTemplate.html'
], function($, _, Backbone, validate, getBusiness, homeTemplate){
var HomeView = Backbone.View.extend({
el: $("#page"),
events: {
'click #data': 'data'
},
data: function(e) {
getBusiness.fetch({
success: function(r) {
},
error: function(r) {
alert('error!');
}
});
},
render: function(){
this.$el.html(homeTemplate);
}
});
return HomeView;
});
The Model:
define([
'underscore',
'backbone'
], function(_, Backbone) {
var getModel = Backbone.Model.extend({
});
return getModel;
});
The Collection:
define([
'jquery',
'underscore',
'backbone',
'models/getModel'
], function($, _, Backbone, getModel){
var getBusiness = Backbone.Collection.extend({
model: getModel,
url: '../../json/data.json',
sync: function(method, model, options) {
options.timeout = 100000;
options.contentType = "application/json";
options.cache = false;
options.dataType = "json";
return Backbone.sync(method, model, options);
},
parse: function(response) {
return this.result;
},
});
return new getBusiness;
});

Resources