I'm new to Backbone.js and Parse so apologies if I'm not specific enough.
I've got a view that throws a TypeError upon initialisation that even if I fix by deleting the line in question, just throws up another error in code that is otherwise perfectly acceptable.
Here is the error I get:
Uncaught TypeError: Cannot call method 'bind' of undefined views.js:59
Uncaught TypeError: Cannot call method 'bind' of undefined views.js:59
Here is the view's init function, lines 59 and 60:
initialize: function() {
this.model.bind("reset", this.render, this);
this.model.bind("add", this.appendNewJob, this);
}
Please let me know in the comments if you need more code to go on.
UPDATE: as requested, my render and appendNewJob functions:
render: function(eventName) {
_.each(this.model.models, function(job){
this.appendNewJob(job);
}, this);
this.delegateEvents();
return this.el;
},
appendNewJob: function(job){
this.$el.append(new JobListItemView({
model: job
}).render());
}
My router:
var AppRouter = Parse.Router.extend({
initialize: function() {
$('#header').html(new HeaderView().render());
},
routes: {
"": "list",
"jobs": "list",
"settings": "viewSettings"
},
list: function() {
var self = this;
FB.getLoginStatus(function(response){
if(response.status === 'connected') {
// logged in.
self.before(function() {
self.showView('#content', new JobListView());
});
} else if(response.status === 'not_authorized') {
// not authorized.
} else {
// not connected.
$('#app').hide();
self.before(function() {
self.showView('#login', new StartView());
});
}
});
},
viewSettings: function() {
var self = this;
FB.getLoginStatus(function(response){
if(response.status === 'connected') {
// logged in.
self.before(function() {
self.showView('#content', new SettingsView());
});
} else if(response.status === 'not_authorized') {
// not authorized.
} else {
// not connected.
$('#app').hide();
self.before(function() {
self.showView('#login', new StartView());
});
}
});
$('#filterBar').hide();
},
showView: function(selector, view) {
if(this.currentView) this.currentView.close();
$(selector).html(view.render());
this.currentView = view;
return view;
},
before: function(callback) {
if(this.jobList) {
if(callback) callback.call(this);
} else {
this.jobList = new JobCollection();
var self= this;
this.jobList.fetch({
success: function() {
var joblist = new JobListView({
model: self.jobList
}).render();
$('#content').html(joblist);
if(callback) callback.call(self);
}
});
}
}
});
UPDATE: I am also using the parse js library in place of backbone.
You are initializing your view without passing in the model option. The error is a standard javascript error, which tells you that on line 59 this.model is undefined:
this.model.bind("reset", this.render, this);
The view cannot have a this.model property, unless you give the model to the view!
So instead of:
new JobListView();
You need to initialize it with
new JobListView({model: <insert your model here>});
Related
I'm currently running some tests with postman where I get a schema and try to validate my results against it.
I know the schema is not consistent with the response I'm getting but I wanted to know how is it possible to expand the results to give a bit more information.
so for example if I have a request like this:
GET /OBJ/{ID}
it just fails with the feedback:
Schema is valid:
expected false to be true
I was hoping to manage to get a bit more feedback in my newman report
this is an example of my test:
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
// only preform tests if response is successful
if (pm.response.code === 200) {
var jsonData = pm.response.json();
pm.test("Data element contains an id", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.id).eql(pm.environment.get("obj_id"));
});
pm.test('Schema is valid', function() {
pm.expect(tv4.validate(jsonData, pm.globals.get("objSchema"))).to.be.true;
});
}
and this is how I run my tests:
const newman = require('newman');
newman.run({
insecure: true,
collection: require('../resources/API.postman_collection.json'),
environment: require('../resources/API.postman_environment.json'),
reporters: 'htmlextra',
reporter: {
htmlextra: {
export: './build/newman_report.html',
logs: true,
showOnlyFails: false,
darkTheme: false
}
}
}, function (err) {
if (err) {
throw err;
}
console.log('collection run complete!');
});
is there a way I can get more information about the validation failure?
I tried a few quick google search but have not come up to nothing that seemed meaningful
it's not exactly what I wanted but I managed to fix it with something like this:
// pre-check
var schemaUrl = pm.environment.get("ocSpecHost") + "type.schema";
pm.sendRequest(schemaUrl, function (err, response) {
pm.globals.set("rspSchema", response.json());
});
// test
var basicCheck = () => {
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
pm.test("Response time is less than 200ms", function () {
pm.expect(pm.response.responseTime).to.be.below(200);
});
};
// create an error to get the output from the item validation
var outputItemError = (err) => {
pm.test(`${err.schemaPath} ${err.dataPath}: ${err.message}`, function () {
pm.expect(true).to.be.false; // just output the error
});
};
var itemCheck = (item, allErrors) => {
pm.test("Element contains an id", function () {
pm.expect(item.id).not.eql(undefined);
});
var Ajv = require('ajv');
ajv = new Ajv({
allErrors: allErrors,
logger: console
});
var valid = ajv.validate(pm.globals.get("rspSchema"), item);
if (valid) {
pm.test("Item is valid against schema", function () {
pm.expect(valid).to.be.true; // just to output that schema was validated
});
} else {
ajv.errors.forEach(err => outputItemError(err));
}
};
// check for individual response
var individualCheck = (allErrors) => {
// need to use eval to run this section
basicCheck();
// only preform tests if response is successful
if (pm.response.code === 200) {
var jsonData = pm.response.json();
pm.test("ID is expected ID", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.id).eql(pm.environment.get("nextItemId"));
});
itemCheck(jsonData, allErrors);
}
}
individualCheck(true);
just create a function to do an item test where I do a stupid assert.false to output each individual error in the schema path
Know how to get list of tasks from a Rally story object? The Tasks is list in story. I tried with story.get("Tasks") and story.getCollection("Tasks"). But both the methods throw undefined error in debugger
Ext.Array.each(stories, function(story){
var storyTasks = ***story.get('Tasks');***
storyTasks.load({
fetch: ['Owner', 'FormattedID'],
callback: function(records, operation, success){
Ext.Array.each(records, function(record){
taskOwners.push({owner: record.get('Owner'),
points: story.PlanEstimate});
}, this);
},
scope: this
});
});
There's a really nice example of how to do this in the docs:
https://help.rallydev.com/apps/2.1/doc/#!/guide/collections_in_v2-section-collection-fetching
Here is an example that does it with promises:
launch: function() {
var stories = Ext.create('Rally.data.wsapi.Store', {
model: 'UserStory',
fetch: ['Tasks']
});
stories.load().then({
success: this.loadTasks,
scope: this
}).then({
success: function() {
//great success!
},
failure: function(error) {
//oh noes!
}
});
},
loadTasks: function(stories) {
var promises = [];
_.each(stories, function(story) {
var tasks = story.get('Tasks');
if(tasks.Count > 0) {
tasks.store = story.getCollection('Tasks');
promises.push(tasks.store.load());
}
});
return Deft.Promise.all(promises);
}
I passed a function as a filter in my WSAPI query, however it seems to have no effect on the results returned. Are there fields which cannot be filtered upon by using this method?
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
Ext.create('Rally.data.WsapiDataStore', {
model : 'TestCase',
fetch : ['TestCases'],
filters : [
function(item) {
return item.FormattedID.indexOf('10') !== -1;
}
]
}).load({
callback: function(records) {
//All records returned, no filter applied
}
});
}
});
I also expected your code to work, but perhaps callback happens before the client side filter is applied. Here is a modified version of the code where the filter is applied and only one record is returned as expected:
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
var myStore = Ext.create('Rally.data.WsapiDataStore', {
model : 'TestCase',
fetch : ['FormattedID']
});
myStore.load({
callback: function(records) {
myStore.filterBy(function(item) {
return item.get('FormattedID').indexOf('10') !== -1;
});
console.log(myStore.getRange()); //one record
}
});
}
});
I am working with grails 2.1.0 and extjs 4.1.0 . Now I am facing some problem here with the success method. The problem is in the code below in comment. Can anyone help me on this :
onupdateOrder : function(invoiceid, payMethod, rebatevalue){
if(invoiceid > 0){
Ext.Msg.confirm('Update Product', 'Are you sure?', function (button) {
if (button == 'yes') {
var invoice = Ext.create('Ext4Example.model.Invoice',{
id : invoiceid,
rebate : rebatevalue,
paymethod : payMethod
});
invoice.save({
success: function(model) {
var inId = model.getId();
this.updateOrder(invoiceid); //warning:this.updateOrder is not a function
},
failure: function(){
console.log('Unable to save/update');
}
});
}
}, this);
}else{
Ext.Msg.alert("Please Give Invoice Id");
}
},
updateOrder :function(invoiceid){
var order = Ext.create('Ext4Example.model.Order',{
id : invoiceid
});
order.save({
success: function(order) {
console.log(invoiceid);
Ext.getCmp('InvoiceNo').setValue(invoiceid);
Ext.getCmp('itemform2').restoreItem();
},
failure: function(){
console.log('Unable to update');
}
});
}
You need to specify
scope: this
On the invoice.save() method so that the callback runs in the controller scope.
I would like to have the ability to setup and teardown functions for views inside EmberJS, for this example I will say displaying logs that are fetched via AJAX every 5 seconds, buts its a problem I encounter quite a lot
I have created a switchView method here which will handle the setup / teardown events, however right now it cant invalidate itself to show the updated information.
Em.Application.create({
wrapper: $('#content'),
currentView: null,
ready: function() {
this._super();
this.self = this;
Em.routes.add('/log/', this, 'showLogs');
Em.routes.add('*', this, 'show404');
},
switchView: function(name, view) {
if (this.currentView) {
$(document.body).removeClass('page-' + this.currentView.name);
if (this.currentView.view.unload) {
this.currentView.view.unload();
}
this.currentView.view.remove();
}
if (name) {
$(document.body).addClass('page-' + name);
}
if (view.load) {
view.load();
}
view.appendTo(this.wrapper);
this.currentView = {name: name, view: view};
}
});
var LogView = Ember.View.create({
templateName: 'logs',
logs: [],
load: function() {
var self = this;
this.interval = setInterval(function() {
self.fetchLogs.apply(self);
}, 5000);
this.fetchLogs();
},
unload: function() {
clearInterval(this.interval);
},
fetchLogs: function() {
var self = this;
$.get('/logs', function(data) {
self.logs = data.list;
});
}
});
I'm not 100% clear on what you're asking for, but you should look into willInsertElement, didInsertElement and willDestroyElement. These are all called relative to the view element's insertion and removal from the DOM.
You can do this at the end of the RunLoop:
Ember.run.schedule('timers', function () {
//update your widget
});
See http://blog.sproutcore.com/the-run-loop-part-1/. The same concept is present in EmberJS