Why click event in backbone not working? - backbone.js

//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>'`)

Related

How to hide the div after sometime in angular or css?

I have one div, initially it is hidden. But on click of the button i am showing it using angular ng-show directive. After showing for 2 seconds i want to hide it. How to do it using angular or css anyone is ok.
HTML code
<div class="subcontent tinyUrlContainer">
<span class="slabel col-md-2">WAP Link :</span>
<div class="input-group col-md-6">
<input type="text" ng-model="wapLink" class="form-control">
<span class="input-group-btn" my-Tooltip>
<button type="button" class="btn btn-default" clipboard supported="supported" text="wapLink" ng-click="clipboard=true" on-error="fail(err)"><img class="clippy" src="./images/surveys/tinyUrl.png" width="13" alt="Copy to clipboard" data-pin-nopin="true"></button>
</span>
</div>
</div>
<span class="copied col-md-offset-6 col-lg-offset-5 col-md-1" ng-show="clipboard">Copied!</span>
on click of the button am setting the clipboard as true and in .copied class element ng-show="clipboard" am setting.
On HTML
ng-show=someCondition()
On your controller
var show = false;
function someCondition(){
return show;
}
function onClick(){
show = true;
$timeout(function(){
show= false
}, 2000);
}
$scope.theClickFunction(){
$scope.theShowFlag = true;
$timeout(function(){
$scope.theShowFlag = false;
}, 2000);
}

Broadcast from directive to controller

I am trying to modify a form in a view by means of a button in my directive's template (template is in another file), this is for a basic CRUD where each item has a delete/edit button.
In order to avoid replicating the form I decided to that on edit's click a function would send the item to the controller in questions in order to be updated with the new information.
But I've been having troubles making the connection, so far I tried changing $root, to $rootScope back and forth and using , $broadcast or $emit.
So how can I send the function onChange my item's information based on the template's button click?
Template:
<strong>{{item.type}}</strong> {{item.description}}
<div class="material-switch pull-right">
<button type="button" class="btn btn-warning btn-circle" ng-show="item.editable" ng-click="onChange()">
<span class="glyphicon glyphicon-edit" ></span>
</button>
<button type="button" class="btn btn-danger btn-circle" ng-controller="View1Ctrl" ng-show="item.editable" ng-click="EliminarItem(item)">
<span class="glyphicon glyphicon-minus" ></span>
</button>
<input ng-model="item.isDone"
id="someSwitchOptionDefault{{itemIndex}}"
name="someSwitchOption001{{itemIndex}}"
type="checkbox" />
<label for="someSwitchOptionDefault{{itemIndex}}" class="label-info"></label>
</div>
Directive:
'use strict';
angular.module('myApp.items.directive', [])
.directive('itemSwitch', [ function() {
return {
restrict: 'A',
scope: {
item: '=',
itemIndex: "="
},
templateUrl: 'templates/itemSwitchTemplate.html',
link : function($scope){
$scope.$broadcast('onChange', item);
}
}
}]);
Controller
.controller('View1Ctrl', ['$scope','itemsService',function($scope,itemsService) {
$scope.items = itemsService.getItems();
$scope.classMap = {GROCERIES:"success",CAR:"danger",UNIVERSITY:"warning",PAYMENTS:"info"};
$scope.newItem = {};
$scope.$on('onChange', function(event, args) {
if ($scope.btnEdit) {
$scope.newItem = args;
} else {
$scope.newItem = {};
}
});
$scope.enableEdit = function (item) {
item.editable = true;
};
$scope.disableEdit = function (item) {
item.editable = false;
};
}]);
View
<div class="col-xs-12">
<div ng-model="currentItem" ng-repeat="item in items" item-switch item="item" item-index="$index" class="notice notice-{{classMap[item.type]}}" ng-mouseover="enableEdit(item)" ng-mouseleave="disableEdit(item)">
</div>
<!-- FORMULARIO -->
<form name = "myForm" class="form-horizontal">
<fieldset>
<div id="legend">
<legend class="">Task</legend>
</div>
<div class="control-group">
<!-- Name-->
<label class="control-label">Name</label>
<div class="controls">
<input type="text" name="itemName" ng-model="newItem.name" placeholder="Task Name" class="input-xlarge" ng-required="true" >
<p class="help-block"></p>
</div>
</div>
<div class="control-group">
<!-- Description -->
<label class="control-label">Description</label>
<div class="controls" >
<input type="text" ng-model="newItem.description" placeholder="Task Description" class="input-xlarge">
<p class="help-block"></p>
</div>
</div>
<div class="control-group">
<!-- Button -->
<div class="controls">
<a class="btn icon-btn btn-success" ng-disabled="myForm.$invalid" ng-click="addOrSaveItem()">
<span class="glyphicon btn-glyphicon glyphicon-save img-circle text-success"></span>Save</a>
</div>
</div>
</fieldset>
</form>
</div>
FiddleJS
Look nd Feel
Using "onChange" as an event name is a poor choice as it is likely to conflict with other events with that name. My recommendation is to use the directive's name as part of the event name.
In your directive
angular.module('myApp.items.directive', [])
.directive('itemSwitch', function() {
return {
restrict: 'A',
scope: {
item: '=',
itemIndex: "="
},
template: '<button ng-click="doIt()">Do It</button>',
link : function(scope){
scope.doIt = function() {
scope.$emit('itemSwitch.doIt', scope.item, scope.itemIndex);
};
}
}
});
In your controller
$scope.doItItems = [];
$scope.$on("itemSwitch.doIt", function(item, itemIndex) {
doItItems.push(item);
});
In this example, on each click of the Do It button, an item is pushed to the doItItems list.
In your itemSwitch directive, you can do
$rootScope.$broadcast('onChange', item);
And then you can pick it up in any scope that is listening (in this case, your controller), with
$scope.$on('onChange', function(event, args) { ... }
This works because $broadcast moves downward from parent to children, while $emit moves upward from child to parents.
So for example, $rootScope.$emit would only be picked up by $rootScope.$on since $rootScope has no parents, while $scope.$broadcast would only be available to that scope's children and not to $rootScope.$on, since $rootScope is not a child of $scope

Submit event doesn't work when specifying with class

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
}
});

rendering template html via backbone view

I have a simple page that contains a 3 step wizard. Basically, the user fills out a textbox, clicks next, which loads the next form field.
I have setup all the HTML inside a template and use that template in a backbone view.
The problem is, backbone isn't rendering the HTML inside the template. I just get a blank screen.
Here is my template:
<script type="text/template" id="assessmentTitleTemplate">
<div id="titleDiv">
<label for="title">Title:</label> <input type="text" />
</div>
<div id="choicesDiv" style="display: none;">
<label for="choices">Choices:</label><input type="text" />
</div>
<div id="typeDiv" style="display: none;">
<label for="types">Types:</label>
<select name="type">
<option>red</option>
<option>blue</option>
<option>green</option>
</select>
</div>
<div id="directionControl">
<input type="button" value="Prev" /> <input type="button" value="Next" />
</div>
</script>
This is my backbone javascript code:
"use strict";
var titleView = Backbone.View.extend({
tagName: 'div',
className: 'title',
template: _.template($('#assessmentTitleTemplate').html()),
events: {
'click .next': 'saveProceedNext',
'click .prev': 'ProceedPrev'
},
initialize: function () {
this.render;
},
render: function () {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
saveProceedNext: function() {
this.$('#titleDiv').hide();
this.$('#choicesDiv').show();
},
ProceedPrev: function() {
}
});
Your code is correct, but you're missing a couple of parens in your initialize body:
initialize : function () {
this.render(); // it was this.render; before
}
Your code isn't invoking the function.
Also, you're missing class tags for your buttons, or else they won't work when clicked. Adding this will make them work:
<input type="button" value="Prev" class="prev" /> <input type="button" value="Next" class="next" />
Check this JSFiddle.

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();
}
}

Resources