What's the difference between click event handler and ngClick directive? - javascript

<html ng-app>
<head>
<script language="javascript" src="./angular-1.0.6/angular.js"></script>
<script language="javascript">
function scopeReady(s) {
document.getElementById("btn").addEventListener("click", function(event) {
alert(s.items);
s.btnClick();
alert(s.items);
});
}
function ctrl($scope) {
$scope.items = ["abc", "def", "ghi"];
$scope.btnClick = function() {
$scope.items.push("one more");
};
scopeReady($scope);
}
</script>
</head>
<body ng-controller="ctrl">
<li ng-repeat="item in items">{{item}}</li>
<button id="btn">Event Handler</button>
<button ng-click="btnClick()">Angular ngClick</button>
</body>
</html>
As what the code snippet shows, why the click of the first button does not trigger update of DOM? Both ng-click and the event handler invokes the same function to proceed. It's quiet confusing to me.

Event handlers run "outside" of Angular, so Angular doesn't know about the change to items, so the ng-repeat does not re-render. Call s.$apply() to cause Angular to run a digest cycle, which will update your view.
With ng-click, scope.$apply() is called automatically.

Related

Javascript onclick function html

I am trying to customize some public git, and because I am a noob in Jquery/Javascript I do not know how to properly bind an onclick function to the button, so that it will know how to call getStates() function. Yes I know that I could just remove $(function(){ and it would work, but I want to be able to call it within jquery function ?
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>US Hospitals</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.mapbox.com/mapbox.js/v2.2.3/mapbox.js'>
</script>
<link href='https://api.mapbox.com/mapbox.js/v2.2.3/mapbox.css' rel='stylesheet' />
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="/lib/neo4j-web.min.js"></script>
</head>
<body>
<div id="desc">
<div class="row top-row">
<div class="col-xs-6">
<h3 class="heading">US Hospitals</h3>
</div>
<div class="col-xs-6">
<p class="lead"></p>
</div>
<button onclick="$.getStates();">Load States!</button>
</div>
</div>
<div id='map'></div>
<script>
$(function(){
function getStates() {
session
.run(districtQuery)
.then(function(result){
result.records.forEach(function(record) {
drawPolygons(parseWKTPolygons(record.get("wkt")),
record.get("text"));
});
})
}
</script>
</body>
</html>
I get the error saying :
Uncaught TypeError: $.getStates is not a function
at HTMLButtonElement.onclick (index.html:51)
$(function () { })
This is telling the interpreter to run any JavaScript/jQuery code as soon as the page is ready. This are usually referred to as an onready function. You don't typically create other functions inside of here.
Remove:
$(function () { })
Also, the way you are creating the onclick event is wrong. Use getStates() instead of $.getStates()
So all in all, your code should be changed as following:
<button onclick="getStates();">Load States!</button>
<script>
function getStates() {
session
.run(districtQuery)
.then(function(result){
result.records.forEach(function(record)
{
drawPolygons(parseWKTPolygons(record.get("wkt")),
record.get("text"));
});
});
}
</script>
Another way you could fix it is to leave your onready function and create the click event inside. Your getStates() function still needs to be placed outside of the onready function though and you would remove the onclick from the button element.
For example:
<button>Load States!</button>
<script>
$(function() {
$('button').click(function () {
getStates();
});
});
function getStates() {
session
.run(districtQuery)
.then(function(result){
result.records.forEach(function(record) {
drawPolygons(parseWKTPolygons(record.get("wkt")),
record.get("text"));
});
})
}
</script>
Now if you have more than one button on this page, you will need to add an ID or class to distinguish them. Then you'd replace $('button') with for example: $('#load_states_button) if using an ID or $('.button_class') if using a class.
These all produce the same result, so how to do it is just a matter of personal preference.
Hope this helped! Let me know if you have any questions. :)
You could add an id to the button and use something like this:
<button id="load-states">Load States!</button>
Javascript:
$(function() {
function getStates() {
session
.run(districtQuery)
.then(function(result){
result.records.forEach(function(record) {
drawPolygons(parseWKTPolygons(record.get("wkt")),record.get("text"));
});
})
}
// Adding event onClick to button
$('#load-states').on('click', getStates);
});
You can make the function global:
window.getStates = function getStates() {
...
};
Then you can simply use getStates() in the onclick attribute.
Of course, the cleaner way to do this would be to bind the event from JavaScript itself, using jQuery's $.click(). This would require you to add an id attribute to the button tag, or some other way to identify it from jQuery.
Take the function out of $(function() { ... }), because functions called from onclick have to be in the global scope. And call it as getStates(), not $.getStates()
<script>
function getStates() {
session
.run(districtQuery)
.then(function(result){
result.records.forEach(function(record) {
drawPolygons(parseWKTPolygons(record.get("wkt")),
record.get("text"));
});
})
}
</script>

raw JS event does not trigger ng-disabled change

I dont know why below code does not work properly? I was hoping when I select the the picture, the object:selected event is fired and I do see the print out, however the status of ng-disabled on the button does not change? the Toggle checkbox does properly toggle the button's disable though. any reason? do we need to fire anything specific to make angular 'rerender'? thanks
<!doctype html>
<html lang="en" ng-app="testApp">
<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.16/angular.js"></script>
<script src="//fabricjs.com/lib/fabric.js"></script>
<script>
var app = angular.module('testApp', []);
app.controller('mainController', function($scope) {
$scope.buttonDisabled = true;
$scope.canvas = new fabric.Canvas('c');
fabric.Image.fromURL("http://lh3.ggpht.com/WDiCN0jYNq_OfzjMwu07XJ9KWOa5AuMxeojLCgTrjCeAtBNd1AKAglIrJBNHbynsFY2HCE-gtOZQVrpN0eG7thFmydfv0STKREJhWaeklg=s660" , function (img ){
$scope.canvas.add(img);
}, {crossOrigin:"anonymous"});
$scope.canvas.on( 'object:selected', function() {
$scope.buttonDisabled = !$scope.buttonDisabled;
console.log("IsDisabled:", $scope.buttonDisabled);
} )
});
</script>
</head>
<body ng-controller="mainController">
<canvas id="c" width="800" height="500"></canvas>
Toggle<input type="checkbox" ng-model="buttonDisabled"><br/>
<button ng-disabled="buttonDisabled">Button</button>
</body>
</html>
The event listener is a jquery event so your function isn't called within angular context.
You should wrap the function content with $scope.$apply() to start digest cycle which will perform, among other things, dirty check for your scope values, will find that buttonDisabled was changed and will update the view accordingly. Here's how to do it:
$scope.canvas.on( 'object:selected', function() {
$scope.$apply(function () {
$scope.buttonDisabled = !$scope.buttonDisabled;
console.log("IsDisabled:", $scope.buttonDisabled);
});
});

After adding a new element in the DOM, the element does not recognize old script

I have a problem.After adding a new element in the DOM, the element does not recognize old script and the same function that was in this document, how to solve this problem? how to reload the script
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<div id='content'>Content.....</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" ></script>
<script src='js/script.js' type='text/javascript'></script>
</body>
</html>
// script.js //
$('#content').click(function(){
$('body').append('<div id="apended">Click me!</div>');
});
$('#apended').click(function(){
alert('click!');
});
When you use .on('click', function (e) {}) function, it works only for existing elements. To handle click event on all selector elements, even for elements which will be added in future, you can use one of these functions:
$(document).on('click', "#appended", function (e) {
// some code code
alert('click!');
});
or:
$("body").delegate("#appended", "click", function () {
// your code goes here
alert('click!');
});
For more information read article about Understanding Event Delegation
Instead of click function You can use :
1.live(old version)
2.delegate
3.on
But , if you want to use click with immutation of delegate function :
var myFn=function(e){
if(e.target.id=='apended'){
alert('click');
}
}
$(document).click(myFn)
Demo :http://jsfiddle.net/abdennour/7cyjV/

Knockout binding with resets jquery bindings

Given the following code:
<body data-bind="with: localization">
<button id="btnLogin">Login</button>
</body>
And the following javascript
$(function () {
$('#btnLogin').click(function () {
console.log('Clicked');
});
ko.applyBindings(MainView);
});
My console is empty if i click on the button
If I change the markup to this:
<body data-bind="">
<button id="btnLogin">Login</button>
</body>
I get "clicked" in my console when testing.
How can I get my events to work properly?
Here's an alternate way to approach your problem, using Knockout to handle clicks:
<body data-bind="with: localization, click: activate">
<button id="btnLogin">Login</button>
</body>
And define the activate function on your ViewModel:
var Vm = function() {
this.activate = function() {
console.log('view model activated, possibly through click');
};
}
This allows you to re-use the activate logic elsewhere.

jquery.on("click") doens't work as i expected [duplicate]

This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 9 years ago.
i am building a web app. the main navigation of this web app is refreshed with jquery but after the refresh the jquery event doesnt work.
the "on button" has a jquery event bound to it with .on and everytime it is clicked it will append a paragraph. the "reset button" adds another "on button" but the jquery event doesn't apply to it.
i have used the .on method to circumvent that the second "on button" isn't in the DOM when the document is ready.
here is a simple example:
example on jsFiddle
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>blub</title>
<script src="js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$(".reset").click(function() {
$("nav").append('<button class="on">test</button>');
})
var count = 0;
$(".on").on("click", function(){
$(".cont").append("<p>Another paragraph! "+(++count)+"</p>");
});
});
</script>
</head>
<body>
<button class="reset">reset</button>
<nav>
<button class="on">test</button>
</nav>
<div class="cont"></div>
<script>
</script>
</body>
</html>
.on isn't a direct replacement for .live, its syntax is slightly different. If you want it to affect elements added to the DOM later, you need to use it like this:
$(document).on('click', '.on', function(){
});
The problem is hot you use method "on" try this:
<script type="text/javascript">
$(document).ready(function() {
$(".reset").click(function() {
$("nav").append('<button class="on">test</button>');
})
var count = 0;
$(document).on("click",".on", function(){
$(".cont").append("<p>Another paragraph! "+(++count)+"</p>");
});
});
</script>
DEMO
You could also do it very simply this way -- this way the click handler gets assigned to each button as it is created.
$(document).ready(function() {
var count = 0;
$(".reset").click(function() {
$("nav").append($('<button>', {
class: 'on',
html: 'test',
click: function() {
$('.cont').append('<p>Another paragraph! ' + (++count) + '</p>');
}
}));
});
});

Categories