Submit event doesn't work when specifying with class - backbone.js

I have a view which has the "el" set to the form id. I have two buttons in the form, one for submit and one for clear. I cannot figure out how to set an event for each button. For example when I set the events as follows they will not work:
Form Template:
<form id="addTask" action="">
<input type="text" placeholder="Your new task"/>
<input type="submit" id="submit" value="Add Task"/>
<input type="submit" id="clear" value="Clear" />
</form>
Form View:
App.Views.AddTask = Backbone.View.extend({
el: '#addTask',
events: {
'submit .edit': 'submit',
'submit .clear': 'clear'
},
submit: function(e) {
e.preventDefault();
var newTaskTitle = $(e.currentTarget).find('input[type=text]').val();
var task = new App.Models.Task({ title: newTaskTitle });
this.collection.add(task);
},
clear: function() {
// do some stuff
}
});
When I use the below syntax for the "click" event in another view it works.
events: {
'click .delete': 'destroy',
'click .edit': 'edit'
},
I have Googled and cannot find an answer. Funny thing is I found a tutorial where this syntax is used with a submit event:
http://dailyjs.com/2013/01/31/backbone-tutorial-10/
Any assistance is appreciated. Thanks.

The submit event is triggered on the form itself, in your case your "el", not the clicked button.
events: {
'submit': 'onSubmit'
}
Would work, but you wouldn't be able to know which button has been clicked.
If you have to submit button, I guess the correct way to do it would be to have two forms.
Let me know if that helps!
Edit:
If you don't want to change your form:
Form Template:
<form id="addTask" action="">
<input type="text" placeholder="Your new task"/>
<input type="submit" id="submit" value="Add Task"/>
<input type="submit" id="clear" value="Clear" />
</form>
Form View:
App.Views.AddTask = Backbone.View.extend({
el: '#addTask',
events: {
'submit': 'submit',
'click #clear': 'clear'
},
submit: function(e) {
e.preventDefault();
var newTaskTitle = $(e.currentTarget).find('input[type=text]').val();
var task = new App.Models.Task({ title: newTaskTitle });
this.collection.add(task);
},
clear: function() {
// do some stuff
}
});

Related

On form submit determine which submit button action is clicked

How can I get the 'Submit button action' when a form is submitted? For example;
<form data-action="foo">
<button type="submit" name="action" value="update">Update</button>
<button type="submit" name="action" value="cancel">Cancel</button>
</form>
In my Backbone View I am trying to figure which button was clicked:
, events: {
'submit form[data-action="foo"]': 'editSubscription'
}
, editSubscription: function(e)
{
e.preventDefault();
// How can I determine the submit action is 'update' or 'cancel'
// Save the model, ie, implicitly do a POST with action UPDATE or CANCEL
this.model.save({action: 'update' /*or 'cancel'*/}, ...);
}
By getting value of submit button.
$(document).on("click", ":submit", function(e){
alert($(this).val());
});
You can get the button value on click event, use prevent default to stop form submit
var el = document.querySelectorAll('button');
el.forEach(item => {
item.addEventListener('click', function(e){
e.preventDefault();
console.log(e.target.value);
})
})
<form data-action="foo">
<button type="submit" name="action" value="update">Update</button>
<button type="submit" name="action" value="cancel">Cancel</button>
</form>
Here is how you can get notification. Just add id attribute to element and get it from currentTarget.
var eventType = '';
$("button").on("click",function(e){
alert($(e.currentTarget).attr('id')+' clicked');
eventType = $(e.currentTarget).attr('id');
//this.model.save({action: eventType}, ...);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form data-action="foo">
<button type="submit" id="update" name="action" value="update">Update</button>
<button type="submit" id="cancel" name="action" value="cancel">Cancel</button>
</form>
You can achieve that in Vanilla JS in the following way:
document.querySelectorAll('button[type=submit]').forEach(function(btn){
btn.addEventListener('click', function(e){
console.log('You have clicked the button:', this.value);
e.preventDefault();
})
});
<form data-action="foo">
<button type="submit" name="action" value="update">Update</button>
<button type="submit" name="action" value="cancel">Cancel</button>
</form>
OR: If you prefer jQuery:
$('button[type=submit]').on('click', function(e){
console.log('You have clicked the button:', this.value);
e.preventDefault();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form data-action="foo">
<button type="submit" id="update" name="action" value="update">Update</button>
<button type="submit" id="cancel" name="action" value="cancel">Cancel</button>
</form>
The simplest way is by using event.target you can get the value of button and put the condition on that
// you can determine by e.target.value that action is 'update' or 'cancel'
if(e.target.value=='update'){
// Save the model, ie, implicitly do a POST with action UPDATE
this.model.save({action: 'update'}, ...);
}
if(e.target.value=='cancel'){
// Save the model, ie, implicitly do a POST with action CANCEL
this.model.save({action: 'cancel'}, ...);
}
Your updated code:
, events: {
'submit form[data-action="foo"]': 'editSubscription'
}
, editSubscription: function(e)
{
e.preventDefault();
// you can determine by e.target.value that action is 'update' or 'cancel'
if(e.target.value=='update'){
// Save the model, ie, implicitly do a POST with action UPDATE
this.model.save({action: 'update'}, ...);
}
if(e.target.value=='cancel'){
// Save the model, ie, implicitly do a POST with action CANCEL
this.model.save({action: 'cancel'}, ...);
}
}

Repeating a Form in Angular

I've got a form that allows users to create a service. Currently you can only add one provider to that service.
I'd like to allow users to add up to 10 providers, using the "Add Another Provider" button.
Here's my code at the moment:
add-service.html
<form role="form" name="createServiceForm">
<input type="text" ng-model="title">
<h2>Attach Provider</h2>
<input type="text" ng-model="provider.title">
<textarea rows="3" ng-model="provider.description"></textarea>
<button type="submit">Add Another Provider</button>
<button type="submit" ng-click="createService()">Submit</button>
</form>
main.js
$scope.createService = function() {
var newService = {
title: $scope.title,
providers: {
provider: {
title: $scope.provider.title,
description: $scope.provider.description
}
},
};
var promise = ServiceService.add(newService);
};
I could duplicate parts of the code like so:
<input type="text"ng-model="provider1.title">
<input type="text"ng-model="provider2.title">
<input type="text"ng-model="provider3.title">
...
providers: {
provider1: {
title: $scope.provider1.title,
},
provider2: {
title: $scope.provider2.title,
},
provider3: {
title: $scope.provider3.title,
}
...
}
But that seems like a messy solution...
What's the best way to duplicate the provider portion of the form, when you click "Add Another Provider" without repeating it 10 times in my HTML and in my newService object?
You can accomplish what you want by using ng-repeat. I've made providers into an array, which you can then iterate over. You could use ng-repeat with an object if the key is important to you.
Also added a function which will push a new provider onto the array, which will then show in the form.
main.js
$scope.providers = [];
$scope.addProvider = function() {
$scope.providers.push({
title: '',
description: ''
});
};
// Start with one provider
$scope.addProvider();
$scope.createService = function() {
var newService = {
title: $scope.title,
providers: $scope.providers,
};
var promise = ServiceService.add(newService);
};
addService.html
<form role="form" name="createServiceForm">
<input type="text" ng-model="title">
<h2>Attach Provider</h2>
<div ng-repeat="provider in providers">
<input type="text" ng-model="provider.title">
<textarea rows="3" ng-model="provider.description"></textarea>
</div>
<button ng-click="addProvider()">Add Another Provider</button>
<button type="submit" ng-click="createService()">Submit</button>
</form>

AngularJS animation initially does not work, but after first click all is good

I have 2 forms, after loading the page, the 1st is shown and the other is hidden. When I first click Add-button, my animation that reveals the 2nd form does not work. But after the first click, I can click cancel-button and add-button again, then all works properly. How can I get this to work also for the "first click"?
If anyone are interested, I am trying to adapt from the following tutorial http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html
My plunker is here http://plnkr.co/edit/02E8eQFHQVynK3mE1IMg?p=preview
The html is
<div ng-controller="MainCtrl as main" xmlns="http://www.w3.org/1999/html">
<form ng-hide="main.showNewUserForm" class="ff-toggle-animation">
<input type="text" id="search" ng-model="main.username" size="30" placeholder="New username here">
<button type="submit" class="btn btn-primary" ng-click="main.showNewUserForm=true">Add</button>
</form>
<form ng-show="main.showNewUserForm" class="ff-toggle-animation">
Username: <input type="text" id="add" ng-model="main.username" size="30" placeholder="New username here"><br>
Full name: <input type="text" ng-model="main.name" size="30" placeholder="Add new user full name here"><br>
Description: <textarea id="description" rows="2" ng-model="main.description" placeholder="Add user description here"></textarea>
<button type="submit" ng-click="main.save()">Save</button>
<button type="submit" ng-click="main.showNewUserForm=false">Cancel</button>
</form>
Some content after...
</div>
The JavaScript animation part looks like this:
app.animation('.ff-toggle-animation', function() {
return {
addClass : function(element, className, done) {
if(className == 'ng-hide') {
jQuery(element).hide(400, done);
}
else {
done();
}
},
removeClass : function(element, className, done) {
if(className == 'ng-hide') {
/* remove it early so you can animate on it since
it is not possible using element.css() to set
a style using !important */
element.removeClass('ng-hide');
jQuery(element).show(400, done);
}
else {
done();
}
}
};
});
It turnes out that I had not followed the tutorial properly.
Before the line where the ng-hide is removed:
element.removeClass('ng-hide');
I need to hide the element so I can performe the animation, like this:
jQuery(element).hide();
So now the animation for the show-part looks like this:
removeClass : function(element, className, done) {
if(className == 'ng-hide') {
jQuery(element).hide();
/* remove it early so you can animate on it since
it is not possible using element.css() to set
a style using !important */
console.log(element);
element.removeClass('ng-hide');
jQuery(element).show(400, done);
}
else {
done();
}
}

Simple button click in backbone

I am trying out different functionalities using backbone and i came accross a strange one. I am trying to submit a form through backbone. I had done this previously and i cannot find whats wrong with what i am doing.
The code is as follows :
HTML Part
<div clas="loginpage"></div>
<form class="login-user-form">
<input type="text" name="name" id="name" placeholder="Enter Name"><br><br>
<button type="submit" class="btn">Create</button>
</form>
jQuery Part
var UserLogin = Backbone.View.extend({
el:'.loginpage',
initialize:function(){
console.log("Login View Initialized");
},
events:{
'submit .btn' : 'loginuser'
},
loginuser:function(){
console.log("Login Clicked.");
return false;
}
});
var userlogin = new UserLogin();
I get Login View Initialized message in console. But i cannot get the loginuser function to work. The page submits through its default submit functionality.
What am i doing wrong?
1) loginpage doesn't contain the form. Fix:
<div class="loginpage">
<form class="login-user-form">
<input type="text" name="name" id="name" placeholder="Enter Name"><br><br>
<button type="submit" class="btn">Create</button>
</form>
</div>
2)
events : {
'submit' : 'loginuser'
},
loginuser : function(){
console.log("Login Clicked.");
return false; // Stops default html form submission
}
Got it working :
events:{
'submit' : 'loginuser'
}
Got this from the following thread : How do I get backbone to bind the submit event to a form?
Cheers ..:)

Why click event in backbone not working?

//I am using template in view
App.Backbone.UserView = Backbone.View.extend({
tagName: 'li',
className: 'pp-entry group',
template :_.template('<img src="i/pp-pic-8.png" class="pp-pic" alt="" />),
templatedetails:_.template('`<div style="display:none"><div id="pp-details-<%=username%>" class="pp-details"><div class="cta clear"><input type="button" name="" value="Add to my Wallet" class="mar-right-10 addtowallet" /><input type="button" class="mar-right-10 addtogib" name="" value="Add to gib as link" /><input type="button" name="" value="Close" onclick="$.fancybox.close()" /></div></div><.div>'`)
//Here is the click event defined
events:{
"click .addtowallet":"addlinktowallet",
"click .addtogib":"addasgiblink"
},
//Render contents
render: function() {
$(this.el).html(this.template(this.model.toJSON()));
$(this.el).attr('id', 'pp-'+this.model.get('username')); //This is used to set the id for the "li" tag
$('#pp-'+this.model.get('username')).append(this.templatedetails(this.model.toJSON())); //appending to the template
},
//But when i am defining the function the click event does not get triggered
addasgiblink: function(){
alert("gib button clicked");
},
addlinktowallet: function(){
alert("wallet button clicked");
}
});
The question is when i click on the pic as rendered from template a fancybox popup opens where templatedetails is rendered but when i click on the buttons in the popup it does not get triggered. Why the click function is not working?
The HTML that is generated after rendering is
<li id="pp-bikram" class="pp-entry group">
<img class="pp-pic" alt="" src="i/pp-pic-8.png">
<div style="display:none">
<div id="pp-details-bikram" class="pp-details">
<div class="cta clear">
<input class="mar-right-10 addtowallet" type="button" value="Add to my Wallet" name="">
<input class="mar-right-10 addtogib" type="button" value="Add to gib as link" name="">
<input type="button" onclick="$.fancybox.close()" value="Close" name="">
</div>
</div>
</div>
</li>
Till this point everything is working fine but i am not getting why the click event is not not working. Please suggest me some solution.
This cannot work because fancybox is not opening your content directly but its "clonning" it into its own container $('#fancybox-content').
Nice solution i think is possible by rebinding this container as Backbone.View.$el so you'll have Backbone.events{} working uppon that:
window.FancyboxView = Backbone.View.extend({
events: {
click: 'handleClick'
},
initialize:function () {
this.$trigger = this.$el.find('a.trigger');
this.$trigger.fancybox({
onComplete:$.proxy(function () {
this.setElement($('#fancybox-content')[0]);
}, this)
});
},
handleClick:function (e) {
e.preventDefault();
console.log('woala!')
}
});
In your code while executing this line
$('#pp-'+this.model.get('username'))
that element wont be available in the dom. So what you have to do is
$(this.el).append(this.templatedetails({// Your json}))
As per my observation both this.el and $('#pp-'+this.model.get('username')) are the same the li tag. So refer it as $(this.el). Please let me know if it works
Please update the code as below.
events:{
"click .addtowallet":"addlinktowallet",
"click .addtogib":"addasgiblink"
"click .fancybox":"fancyBoxClose"
},
fancyBoxClose : function(){
$.fancybox.close()
}
templatedetails:_.template('`<div style="display:none"><div id="pp-details-<%=username%>" class="pp-details"><div class="cta clear"><input type="button" name="" value="Add to my Wallet" class="mar-right-10 addtowallet" /><input type="button" class="mar-right-10 addtogib" name="" value="Add to gib as link" /><input type="button" name="" value="Close" class="fancybox" /></div></div><.div>'`)

Resources