Backbone collection's fetch method not calling? - backbone.js

i am using yoeman scaffolding to create and build a Backbone project. i am trying below code unable to fetch collection's data in view's initialize block. i am not getting any error in console. i tried to debug but it's not going in success block. can you anyone tell me the correct way to consume collection in Backbone View.
contacts.json
[
{
"id": 1,
"name": "first name",
"mobile": "xxx-xxx-xxxx",
"email": "anshuls#abc.com"
},
{
"id": 2,
"name": "second name",
"mobile": "xxx-xxx-xxxx",
"email": "anshuls#abc.com"
}
]
//model
define([
'underscore',
'backbone'
], function (_, Backbone) {
'use strict';
var ContactModel = Backbone.Model.extend({
initialize: function() {
},
defaults: {
name:null,
mobile:null,
email:null,
avatar:null
}
});
return ContactModel;
});
//collection
define([
'underscore',
'backbone',
'models/contact'], function (_, Backbone, ContactModel) {
'use strict';
var ContactCollection = Backbone.Collection.extend({
model: ContactModel,
url: 'scripts/json/contacts.json',
initialize: function () {
}
});
return ContactCollection;
});
//view
define([
'jquery',
'underscore',
'backbone',
'templates',
'../views/contact',
'../collections/contact'
], function ($, _, Backbone, JST, ContactView, ContactCollection) {
'use strict';
var ContactsView = Backbone.View.extend({
template: JST['app/scripts/templates/contacts.hbs'],
initialize: function () {
var self = this;
this.collection = new ContactCollection();
this.collection.fetch({
success: function (collection,response) {
console.log('Collection fetch success' + response);
console.log('Collection models: ' + collection.models);
}
});
}
})
return ContactsView;
});

Try adding an error block to your collection.fetch, and see if the error block is being called:
this.collection.fetch({
success: function (collection,response) {
console.log('Collection fetch success' + response);
console.log('Collection models: ' + collection.models);
},
error: function(model, xhr, options) {
console.log('error'); <-- debug here
}
});

Does the collection actually make the request for the data? do you see it in the network tab?

Related

angular service test fails to return required response

I am trying to write tests for angular service using jasmine and karma. I have the following code for my service call:
angular.module('omdb', [])
.factory('myservice', MyService);
MyService.$inject = ['$http'];
function MyService($http) {
var vm = this;
var service = {};
service.getData = function() {
return $http.get('omdb/mydata.json').then(function(response) {
return response.data;
});
};
return service;
};
I am tesitng it using the following file for spec as:
describe('myservice', function() {
var mockservicedata = [{
"name": "value1",
"id": "1"
}, {
"name": "value2",
"id": "2"
}, {
"name": "value3",
"id": "3"
}];
var myservice = {};
beforeEach(module('omdb'));
beforeEach(inject(function(_myservice_) {
myservice = _myservice_;
}));
it('should return search myservice data', function() {
expect(myservice.getData()).toEqual(mockservicedata);
});
});
which basically throws an error as:
Expected d({ $$state: Object({ status: 0 }) }) to equal [ Object({ name: 'value1', id: '1' }), Object({ name: 'value2', id: '2' }), Object({ name: 'value3', id: '3' }) ].
stack#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1482:17
buildExpectationResult#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1452:14
Env/expectationResultFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:583:18
Spec.prototype.addExpectationResult#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:324:29 addExpectationResult#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:533:16
Expectation.prototype.wrapCompare/<#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1406:7
#http://localhost:59239/movie-app/spec/omdb/myservice.spec.js:14:9
attemptSync#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1789:9
QueueRunner.prototype.run#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1777:9 QueueRunner.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1762:5
Env/queueRunnerFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:627:7
Spec.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:353:5 executeNode/<.fn#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:2360:32 attemptAsync#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1819:9
QueueRunner.prototype.run#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1774:9
QueueRunner.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1762:5
Env/queueRunnerFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:627:7
executeNode/<.fn#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:2345:13 attemptAsync#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1819:9
QueueRunner.prototype.run#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1774:9
QueueRunner.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1762:5
Env/queueRunnerFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:627:7
TreeProcessor/this.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:2209:7
Env/this.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:678:7
window.onload#http://localhost:59239/movie-app/lib/jasmine-2.3.4/boot.js:110:5
I don't understand why it does not return data to the test. please help
Calling myservice.getData() won't actually give you the data you're expecting.
Since your getData method from MyService relies on $http's get method, you should be mocking it and then expecting that data returned.
So your test case should be like:
describe('myservice', function() {
var mockservicedata = [{
"name": "value1",
"id": "1"
}, {
"name": "value2",
"id": "2"
}, {
"name": "value3",
"id": "3"
}];
var myservice = {};
beforeEach(module('omdb'));
beforeEach(inject(function(_myservice_, _$httpBackend_) {
myservice = _myservice_;
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', "omdb/mydata.json").respond({
status: 200,
data: mockservicedata
});
}));
it('should return search myservice data', function() {
var response = myservice.getData()
response.then(function(response) {
expect(response.data).toEqual(mockservicedata);
});
$httpBackend.flush();
});
});
Hope this helps.
getData() will never return data instead it will return promise object.
If you want to test it then firstly you would have to mock the data for service then you can call it and match the result in the success handler.
Code is attached below:
describe('myservice', function() {
var mockservicedata = [{
"name": "value1",
"id": "1"
}, {
"name": "value2",
"id": "2"
}, {
"name": "value3",
"id": "3"
}];
var myservice, httpBackend;
beforeEach(module('omdb'));
beforeEach(inject(function(_myservice_, $httpBackend) {
myservice = _myservice_;
httpBackend = $httpBackend;
}));
it('should return search myservice data', function() {
httpBackend.when("GET", "omdb/mydata.json").respond(mockservicedata);
var promise = myservice.getData();
promise.then(function(response) {
expect(response.data).toEqual(mockservicedata);
});
httpBackend.flush();
});
});

UI-Grid not displaying JSON data?

I have what I think is the correct accessor syntax for binding my UI-Grid control, I don't get any errors or any data. I just get a warning about Mutating the prototype.
My json data structure is like this:
{
"records": [
{
"acctIdInfo": {
"acctId": "257905480",
"acctCode": "ABC10101102",
"acctName": "BIG CORPORATION",
"acctRole": [
"C"
]
},
"acctNameAddr": {
"addressLine": [
"7280 JAMISON ST"
],
"cityName": "VANCOUVER",
"stateCd": "US-WA",
"countryCd": "US",
"postalCd": "97979"
}
}
]
}
The code in my AngularJS controller to bind is:
var app = angular.module('app', ['ui.grid', 'ngResource'])
.factory('jsonDataFactory', function ($resource) {
return {
custData: $resource('data.json', {}, {
query: {method: 'GET', params: {}, isArray: false}
}),
};
});
app.controller('MainCtrl', ['$scope','$resource','jsonDataFactory', function ($scope,$resource, jsonDataFactory) {
$scope.gridOptions = {
enableRowSelection: true,
enableSelectAll: true,
selectionRowHeaderWidth: 35
};
$scope.gridOptions.columnDefs = [
{ name: 'acctIdInfo.acctId' },
{ name: 'acctIdInfo.acctCode'},
{ name: 'acctIdInfo.acctName'},
{ name: 'acctNameAddr.addressLine' }
];
$scope.gridOptions.data = jsonDataFactory.custData.query().records;
$scope.CustomerData = [];
$scope.CustomerData = jsonDataFactory.custData.query();
console.log($scope.CustomerData);
$scope.gridOptions.data = $scope.CustomerData.records;
}]);
Here is my plnk of what I tried -
I think I'm close...
Do assign a data to ui-grid data source once ajax call response comes back. I assumed that you had used $resource, so you can have promise over it to attach callback function.
jsonDataFactory.custData.query().$promise.then(function(response){
$scope.CustomerData = response;
console.log($scope.CustomerData);
$scope.gridOptions.data = $scope.CustomerData.records;
});

AngularJS deferred $http.get response, empty array

Please help in changing this code to be able to use $http.get html, at the moment the resulting array (html_controls) is empty. However, I can see the response in the console for all the request in $http.get. Thank you.
angular.module('exodus-grid').controller('DynamicPropertiesController', ['$scope', '$http', '$templateCache', '$q', 'coreFactory',
function($scope, $http, $templateCache, $q, coreFactory) {
//$scope.DynamicProperties = 'Property being added to the controller.';
//coreFactory.fetchData('http://uat.resources.newscdn.com.au/cs/networksales/products/latest/products.json', 'products');
// TODO: Change this harcoded value to the products.json in s3
$scope.products = [{
"id": "btyb",
"label": "BTYB + Superskin",
"description": "",
"name": "btyb",
"active": true,
"properties": [{
"bannerLink": [{
"tmp_prop_name": "bannerLink",
"label": "Header Tracking Link (Desktop)",
"type": "textbox"
}],
"superskinLink": [{
"tmp_prop_name": "superskinLink",
"label": "Sideskin Tracking Link (Desktop)",
"type": "textbox"
}],
"ImgUrl": [{
"tmp_prop_name": "ImgUrl",
"label": "Header Image Url",
"type": "textbox"
}]
}]
}, {
"id": "iframe",
"label": "iframe",
"description": "",
"name": "iframe",
"active": true,
"properties": [{
"link": [{
"tmp_prop_name": "link",
"label": "iFrame source Url",
"type": "textbox"
}]
}]
}];
var requests = [];
var html_controls = [];
var product = $scope.products[0];
var properties = angular.fromJson(product.properties);
//console.log(angular.toJson(properties));
angular.forEach(properties, function(property) {
angular.forEach(property, function(item) {
//console.log(angular.toJson(property));
if (item[0].type === "textbox") {
//console.log(angular.toJson(item));
//console.log(Object.getOwnPropertyNames(property));
//console.log(Object.keys(property));
$http.get("plugins/k-plugin-exodus-grid/templates/properties/textbox.html").success(function(html) {
html = html.replace("%%label%%", item[0].label);
html = html.replace("%%scope%%", item[0].tmp_prop_name);
//console.log(html);
html_controls.push(html);
console.log(html_controls);
var deferred = $q.defer();
requests.push(deferred.promise);
console.log(deferred, deferred)
}).then(function() {
//$scope.html = html_controls;
});
}
});
});
//console.log(html_controls);
//$scope.html = html_controls;
$q.all(requests).then(function(data) {
console.log("12312312 " , data);
$scope.html = html_controls;
});
}
]);
Looks like you are trying to resolve a array of empty promises. Since it is running async, when $q.all() us called, requests[] is still empty.
Try building an array of promises and then resolve this using q.all() instead:
var requests = []; // a list of promises
angular.forEach(properties, function(property) {
angular.forEach(property, function(item) {
var promise = $http.get("/yoururl"); // $http.get returns a promise
requests.push(promise); // add to list of requests as a promise
});
});
$q.all(requests).then(function (result) {
console.log('results' + result);
});

$.fn.dataTable.Editor is not a constructor - RequireJS with DataTables

Library versions:
jQuery : 2.1.1
DataTables : 1.10.1-dev
dataTablesTableTools : 2.2.1
dataTables.dataTables.editor.min.js : 1.2.3
I'm trying to implement CRUD operation using datatableseditor using Backbone, RequireJS and Datatables.But I'm getting the error message:
$.fn.dataTable.Editor is not a constructor"
What could be the reason?
Here is my configuration:
require.config({
baseUrl: 'js',
paths: {
jquery: 'vendor/jquery.min',
datatables: 'vendor/jquery.dataTables.min',
datatablesTableTools: 'vendor/dataTables.tableTools.min',
datatablesEditor: 'vendor/dataTables.editor.min'
},
shim: {
jquery : {
exports : '$'
},
datatables: {
deps: [
'jquery',
]
},
datatablesTableTools: { deps: ['datatables'] },
datatablesEditor: { deps: ['datatables'] }
}
});
Using it as follows:
require(["jquery", "datatables"], function () {
var editor = new $.fn.dataTable.Editor( {
"ajax": "table.line.php"
} );
$('#myGrid').dataTable( {
"aaData": [
['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C']
],
"aoColumns": [
{ "sTitle": "Engine" },
{ "sTitle": "Browser" },
{ "sTitle": "Platform" },
{ "sTitle": "Version" },
{ "sTitle": "Grade" }
],
"tableTools": {
"sRowSelect": "os",
"aButtons": [
{ "sExtends": "editor_create", "editor": editor },
{ "sExtends": "editor_edit", "editor": editor },
{ "sExtends": "editor_remove", "editor": editor }
]
}
});
});
I think you have made a mistake in your table of dependencies. In your second code, it should be like this :
require(["jquery", "datatablesEditor"], function () {
[...]
instead of
require(["jquery", "datatables"], function () {
[...]
I've checked and it's more vicious. When you look the source code of the plugin datatables-fixedcolumns for example, its name is specified so you need to use it instead of your own alias/name.
The source code dataTables.fixedColumns.js :
[...]
// Define as an AMD module if possible
if ( typeof define === 'function' && define.amd ) {
define( 'datatables-fixedcolumns', ['jquery', 'datatables'], factory );
}
else if ( jQuery && !jQuery.fn.dataTable.FixedColumns ) {
// Otherwise simply initialise as normal, stopping multiple evaluation
factory( jQuery, jQuery.fn.dataTable );
}
[...]
So in your requirejs.config, you need to write this :
[...]
paths: {
jquery: 'vendor/jquery.min',
datatables: 'vendor/jquery.dataTables.min',
datatables-fixedcolumns: 'vendor/dataTables.fixedColumns'
[...]
instead of
[...]
paths: {
jquery: 'vendor/jquery.min',
datatables: 'vendor/jquery.dataTables.min',
datatablesFixedColumns: 'vendor/dataTables.fixedColumns'
[...]

Backbone (Marionette) fetch in a collection returns an empty array (nested models)

I'm working with nested models and collections in Backbone (Marionette).
// Basic unit
Models.User = Backbone.Model.extend({});
Models.Users = Backbone.Collection.extend({ model: Models.User });
// A Group has a collection of Users
Models.Group = Backbone.Model.extend({
initialize: function() {
var users = new Models.Users(this.get("users"));
this.set("users", users);
}
});
Models.Groups = Backbone.Collection.extend({ model: Models.Group });
// An Organization has a collection of Groups
Models.Organization = Backbone.Model.extend({
initialize: function() {
var groups = new Models.Groups(this.get("groups"));
this.set("groups", groups);
}
});
Models.Organizations = Backbone.Collection.extend({
model: Models.Organization,
url: "./data/data.json"
});
My understanding is that this.get will return an array of objects (as determined via the data.json file) and convert it to a Backbone Collection.
The data.json file has the following structure:
[{
"id": "org1",
"groups": [{
"id": "group1",
"users": [
{ "name": "Alice" },
{ "name": "Bob" }
]
},
{
"id": "group2",
"users": [{ "name": "Charlie" }]
}]
},
{
"id": "org2",
"groups": [{
"id": "groupA",
"users": [{ "name": "Eve" }]
},
{
"id": "groupB",
"users": [
{ "name": "Linda" },
{ "name": "Mallory" }
]
}]
}]
I'm trying to populate the top-most collection (an Organization) with the data from data.json.
In index.html, I have:
<script type="text/javascript">
$(document).ready(function() {
MyApp.OrgManager.addInitializer(function() {
var data = new MyApp.Models.Organizations();
data.fetch({
success: function(collection) {
console.log("Success", collection);
}
});
});
MyApp.start();
});
</script>
fetch returns successfully, but the output of my console for the collection is an empty array. What went wrong?
Solved it. Had to make sure that
I was running the page on a local webserver, since jQuery doesn't like null origin XMLHttpRequests, and
I had to _.bindAll a few things so that this had a proper context.

Resources