BackboneForms different key than display possible? - javascript

I have a very simple form:
var UserForm = Backbone.Form.extend({
template: _.template($('#formTemplate').html()),
schema: {
venue: { validators: ['required'] },
},
model: this.model
});
This create a label with name Venue and puts a textfield beside it. But what if I want to name the label VenueName and keep the key it assigns to model venue. Is this possible? Thanks!

From the documentation yes, this is very easy:
var UserForm = Backbone.Form.extend({
template: _.template($('#formTemplate').html()),
schema: {
venue: {
validators: ['required'],
title: 'Venue Name'
},
},
model: this.model
});

Related

Issues with dynamic routing using meteor-autoform and iron:router

What I am trying to do is create a form with meteor-autoform that will redirect the user to a newly generated route on submit. My thought process is that I can take the submissions _id and use it for an iron:router parameter. What I have so far looks as followed:
Creation of Form
Submits = new Meteor.Collection('Submits');
Submits.allow({
insert: function(username, doc){
return !!username;
}
});
SubmitSchema = new SimpleSchema({
title: {
type: String,
label: "Title"
},
subject:{
type: String,
label: "Subject"
},
summary:{
type: String,
label: "Summary"
},
author:{
type: String,
label: "Author",
autoValue: function() {
return this.userId
},
autoform: {
type: "hidden"
}
},
createdAt: {
type: Date,
label: "Created At",
autoValue: function(){
return new Date()
},
autoform: {
type: "hidden"
}
}
});
Submits.attachSchema( SubmitSchema );
Routing
Router.route('/submit', {
layoutTemplate: 'submitLayout',
waitOn: function() { return Meteor.subscribe("Submits"); },
loadingTemplate: 'loading'
});
Router.route('/submit/:_id', {
name: 'formDisplay',
data: function() {
return Submits.findOne({this.params._id});
}
});
And then I just have the average publish and find calls. My issues are I'm not sure how to perform the redirect on submit, and I am not sure how to display the form results on the newly generated route.
Any help would be appreciated.
I was able to do it by adding an autoform.hook and changing my routing a bit.
Autoform hook:
AutoForm.addHooks('insertSubmit', {
onSuccess: function(doc) {
Router.go('formDisplay',{_id: this.docId});
}
})
Routing:
Router.route('/submit/:_id', {
name: 'submitLayout',
data: function() { return Products.findOne(this.params._id);}
});
I got this information from this post:
Route to the new data submitted by Meteor autoform using iron router?

Backbone js - change model attributes

I have a backbone model:
App.Models.Education = Backbone.Model.extend({
schema: {
university: {
type: 'Text',
validators: ['required'],
editorAttrs: {placeholder: 'Test placeholder'}
},
info: {type: 'Text'},
desc: {type: 'Text'}
})
and extend it:
App.Models.HighSchool = App.Models.Education.extend({
initialize: function () {
//code to change placeholder
this.set({education_type: init_parameters.school});
}
});
How to change the placeholder text in "university" field of HighSchool?
I wouldn't recommend setting up your models that way. You should try to avoid nesting attributes because of the exact same issue you're having. It becomes hard to change one particular field.
Instead, can you do something like:
App.Models.Education = Backbone.Model.extend({
defaults: { // backbone keyword to have default model attributes
type: 'Text',
validators: ['required'],
editorAttrs: {placeholder: 'Test placeholder'
}
});
App.Models.HighSchool = App.Models.Education.extend({
initialize: function () {
//code to change placeholder
this.set('editorAttrs', {placeholder: 'new placeholder'});
this.set('education_type', init_parameters.school);
}
});

Model doesn't change when modify view elements in backbone.js

I am validating model's attribute (Name), in order to make sure, customer have to input their name in the register form.
View :
define(["jquery" ,
"underscore" ,
"backbone" ,
"text!templates/CustomerTemplate.html",
"models/Customer"
],function($ , _ , Backbone, CustomerTemplate, CustomerModel){
var CustomerView = Backbone.View.extend({
initialize : function(){
this.listenTo(this.model, 'change', this.render);
},
events : {
'submit #customerForm' : 'Customer'
},
Customer : function(e){
e.preventDefault()
var _customer = new CustomerModel({
UID: "00000000-0000-0000-0000-000000000000",
Sex: 0,
Name: $("#name").val(),
});
this.model.save(_customer,{validate: true},{
wait:true,
success:function(model, response) {
console.log('Successfully saved!');
},
error: function(model, error) {
console.log(model.toJSON());
console.log('error.responseText');
}
});
},
render : function(){
var customertemplate = _.template(CustomerTemplate);
this.$el.html(customertemplate(this.model.toJSON()));
return this;
}
});
return CustomerView;
});
Model:
define(["underscore" , "backbone"],function(_ , Backbone){
var CustomerModel = Backbone.Model.extend({
urlRoot: "myurl",
initialize : function(){
this.bind('invalid', function(model, error) {
console.log(error);
});
},
validate: function (attrs){
if ( !attrs.Name) {
return 'You must provide a name';
}
},
defaults : {
UID: "00000000-0000-0000-0000-000000000000",
Sex: 0,
Name: "",
}
});
return CustomerModel;
});
Problem : Even the attribute Name is not null, the error message in validate method still appears (You must provide a name).
Any idea what could be causing this is appreciate. Thanks.
When you call this.model.save in your CustomerView, you're passing it a new Customer model you instantiated in the previous statement. This isn't quite what you want; you either want to call _customer.save() to save the brand new model, or - more likely - you want to pass your new attributes to the existing model, and save that:
var newAttrs = {
UID: "00000000-0000-0000-0000-000000000000",
Sex: 0,
Name: $("#name").val(),
};
this.model.save(newAttrs);
When you call this.model.save(_customer, {validate: true}) in your existing code, that Customer model get passed to your validate() function. And that model doesn't have a Name attribute. It does have a Name property - you can access it via _customer.get('Name') - but you should follow the Backbone convention and presume that your validate method is getting a 'simple' JavaScript object, not a Backbone model.

Ember.js: Computed property on current element in array

So, this is what my model looks like (represented by fixture data):
var posts = [{
id: 'b026324c6904b2a9',
title: "My new front door",
author: { name: "Matthieu" },
date: new Date('2013-10-28T12:19:30.789'),
status: 'new',
hidden_message: "hidden1"
}, {
id: '26ab0db90d72e28a',
title: "Best pizza in town",
author: { name: "Harry" },
date: new Date('2013-10-28T12:19:30.789'),
status: '',
hidden_message: "hidden2"
}, {
id: '6d7fce9fee471194',
title: "Skateboard dreamland",
author: { name: "Matthieu" },
date: new Date('2013-10-28T12:19:30.789'),
status: 'solved',
hidden_message: "hidden3"
}, {
id: '48a24b70a0b37653',
title: "my house looks like a pumpkin",
author: { name: "Harry" },
date: new Date('2013-10-28T12:19:30.789'),
status: '',
hidden_message: "hidden4"
}];
My route:
App.IndexRoute = Ember.Route.extend({
model: function() {
return posts;
}
});
And, I'd like to be able to display a certain piece of HTML in the template if the corresponding post is new, a different one if it's solved, and nothing if the status is blank. It seems to me as if the best way to do this is using an {{#if}} helper, but that doesn't do equality comparisons, it can only take a boolean variable. So, I'd like to do something like this:
App.IndexController = Ember.ArrayController.extend({
isNew: function(val) {
if(this.get('currentitem.status') === 'new') {
return true;
}
return false;
}.property('isNew')
});
But I can't find out how to select the item being currently accessed by {{#each}} in the template. Is this even possible, and if yes, how do I do it (or something similar)?
Thanks all!
The correct way to do this is to create an itemcontroller that helps you by providing a controller per item in your collection.
App.IndexController = Ember.ArrayController.extend({
itemController: "PostItem",
});
App.PostItemController = Ember.ObjectController.extend({
isNew: function() {
if(this.get('status') === 'new') {
return true;
}
return false;
}.property('status')
});
Then in your handlebar template you can just call {{isNew}} in the {{#each}}-context.
I've put up a working fiddle that you can test it out in.
http://jsfiddle.net/LordDaimos/v8NR3/1/
Best way would probably be to wrap each post in an object that has the isNew method, like this:
var postObject = Ember.Object.extend({
isNew: function() {
if(this.get('status') === 'new') {
return true;
}
return false;
}.property('status')
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return posts.map(function(post){
return postObject.create(post);
});
}
});
this way you could query on each post.

Backbone Collection Can't Remove Items

I've got a Backbone Model called Delivery. I then create a collection of Deliveries called DeliveryList backed by LocalStorage. In my Marionette.ItemView for displaying items in the collection, I have a method to remove items:
removeDeliveryOption: function() {
Deliveries.remove(this.model.get("id"));
}
For some reason, this removes the item from the Marionette.CompositeView when I click the remove button, but when I reload the page the same number of items always reappear.
It's worth noting that when I delete the item, it always reappears with the default optionName "Free Delivery". I'm using both defaults and a schema in the model because I'm using the Backbone-forms plugin (https://github.com/powmedia/backbone-forms).
Any help is greatly appreciated!
var Delivery = Backbone.Model.extend({
defaults: function () {
return {
order: Deliveries.nextOrder(),
optionName: "Free Delivery",
shipToState: "Hawaii",
zipCodes: "96813",
perOrderFee: "0.00",
perItemFee: "0.00"
};
},
schema: {
optionName: { type: 'Text', validators: ['required'] },
shipToState: { type: 'Select', options: getStateNames(), validators: ['required'] },
zipCodes: { type: 'Text', validators: ['required'] },
perOrderFee: { type: 'Text', validators: ['required'] },
perItemFee: { type: 'Text', validators: ['required'] },
}
});
var DeliveryList = Backbone.Collection.extend({
model: Delivery,
localStorage: new Backbone.LocalStorage("deliverylist-backbone"),
nextOrder: function () {
if (!this.length) return 1;
return this.last().get('order') + 1;
},
comparator: 'order'
});
var Deliveries = new DeliveryList;
var deliveryView = Marionette.ItemView.extend({
//tagName: "li",
template: "#delivery-item-template",
events: {
"click #removeThis": "removeDeliveryOption",
},
removeDeliveryOption: function() {
Deliveries.remove(this.model.get("id"));
}
});
var DeliveriesView = Marionette.CompositeView.extend({
initialize: function() {
Deliveries.fetch();
},
template: '#deliveries-view-template',
itemView: deliveryView,
events: {
"click #addShipping": "addDeliveryOption",
},
addDeliveryOption: function() {
var editDeliveryForm = new Backbone.Form({
template: _.template($("#editDeliveryTemplate").html()),
model: Deliveries.create()
}).render();
this.$el.append(editDeliveryForm.el);
$("#triggerEditDelivery").fancybox({
'afterClose': function () {
commitForm(editDeliveryForm);
//Wait do display the inlineModel until here
// Once we've bound the form to the model, put the saving logic with the collection
//Deliveries.last().save();
}
}).trigger('click');
},
// Specify a jQuery selector to put the itemView instances in to
itemViewContainer: "#deliveries",
});
EDIT
Thanks to #ejosafat! Had to destroy the model instead of just removing from collection.
removeDeliveryOption: function() {
this.model.destroy();
}
The remove method only affects the collection loaded in the browser, not in the permanent storage (local or server). That's why it dissappears from the view but when you reload the page it appears again.
If you want to get rid of that model in the storage too, use its destroy method.
(btw, it's a common convention in Javascript to use initial capital letter only for constructor functions, as clue that it should be used with the new operator, or be extended to create a derived constructor/class, so it's a bad idea to use Deliveries as a collection var name)

Categories

Resources