How to access $(this) div in angularjs - html

I want to change the background of div that is clicked. So, how i can access $(this) div in angular?
My code is:
<div id="single" ng-click="changeit()">
foobar
</div>
And function is:
$scope.changeit=function($scope){
// jquery code $(this).css({"background":"#A4A4A4"});
// how in angular ?
}

You can pass the $event and use target to retrieve the current clicked element.
<div id="single" ng-click="changeit($event)">
asad
</div>
$scope.changeit = function ($event) {
$($event.target).css({ 'background': '#A4A4A4' });
}
Using a directive way, you could do it like this :
<div id="single" data-change-color>foobar</div>
And the changeColor directive which adds a click event on the element and changes the color when clicking on it.
(function () {
'use strict';
angular
.module('myModuleName')
.directive('changeColor', changeColor);
changeColor.$inject = [];
function changeColor () {
return {
restrict: 'A',
scope: {},
link: link
};
function link (scope, element) {
element.on('click', onClick(element));
}
function onClick (element) {
return function () {
element.css({ 'background': '#A4A4A4' });
}
}
}
}) ();

DOM manipulation should ideally be the sole domain of directives when using angular. This keeps us from gluing our controller logic into our DOM presentation which makes for a horrible mess. With this in mind Angular has two directives related to styling, ng-style and ng-class. Ng-class is demonstrated below.
https://docs.angularjs.org/api/ng/directive/ngStyle
https://docs.angularjs.org/api/ng/directive/ngClass
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#1.4.3" data-semver="1.4.3" src="https://code.angularjs.org/1.4.3/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<style>
.active{
background:red;
}
</style>
</head>
<body ng-controller="ctrl">
<button ng-click="activeButton = 1" ng-class="{'active' :activeButton==1}">Button 1</button>
<button ng-click="activeButton =2" ng-class="{'active' :activeButton==2}">Button 2</button>
<button ng-click="activeButton = 3" ng-class="{'active' :activeButton==3}">Button 3</button>
<script>
var app = angular.module("app",[]);
app.controller("ctrl",function(){});
angular.bootstrap(document,[app.name]);
</script>
</body>
</html>

Related

jQuery togle “active” class between X number of buttons while adding/removing unique classnames

I have unknown number of buttons for e.g lets say I got 3. Here how my HTML looks like:
<div id="my-lovely-buttons">
<button class="btn-one">1</button>
<button class="btn-two">2</button>
...
<button class="btn-twentytwo">22</button>
</div>
<div class="awesome-element"></div>
Using jQuery I need them to have these conditions:
By default none of buttons have class "active"
When you press respective you can toggleClass("active")
If I press any of them, and one already has class "active" it needs to remove from the sibling and add it the one I just pressed.
Upon pressing one of the buttons, they would toggle another classes for "awesome-element". (please see jQuery code in example below)
If I press for e.g "btn-one" (which added classes for "awesome-element") and then immediately press "btn-two" it needs to remove added classes by "btn-one" and toggle respective classes from "btn-two" (cause "btn-two" now has class "active" and "btn-one" does not. See my jQuery code below)
So my jQuery looked like this:
$(function () {
$('body').on('click', '#my-lovely-buttons', function () {
$(".btn-one").toggleClass("active");
$(".awesome-element").toggleClass("hidden shown");
});
});
$(function () {
$('body').on('click', '#my-lovely-buttons', function () {
$(".btn-two").toggleClass("active");
$(".awesome-element").toggleClass("big small");
});
});
$(function () {
$('body').on('click', '#my-lovely-buttons', function () {
$(".btn-twentytwo").toggleClass("active");
$(".awesome-element").toggleClass("selected");
});
});
As you can see, this code above does not solve condition number "3" as it just toggle "active" class without removing it from the sibling. Also, it does not solve condition number "5". And overall I think it can be written better, maybe within 1 function instead of making a function for every button like I have in my code. I am really new to jQuery, please don't judge.
$(function () {
$('body').on('click', '#my-lovely-buttons', function () {
$(".btn-one").toggleClass("active");
$(".awesome-element").toggleClass("hidden shown");
});
});
$(function () {
$('body').on('click', '#my-lovely-buttons', function () {
$(".btn-two").toggleClass("active");
$(".awesome-element").toggleClass("big small");
});
});
$(function () {
$('body').on('click', '#my-lovely-buttons', function () {
$(".btn-twentytwo").toggleClass("active");
$(".awesome-element").toggleClass("selected");
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="my-lovely-buttons">
<button class="btn-one">1</button>
<button class="btn-two">2</button>
...
<button class="btn-twentytwo">22</button>
</div>
<div class="awesome-element"></div>

$compile not triggering ng-click in angularjs

I am generating dynamic html element from angularjs controller.I have used $compile
to make ng-click work inside html element.But still it is not calling the function.
Here is my js
var accountApp = angular.module('accountApp', ['ngRoute']);
accountApp.config(['$compileProvider',function($compileProvider )
.controller('myController',function($scope,$compile)
{
var searchHTML = '<li><a href="javascript:void(0)" data-ng-
click="setMarkerToCenterA()">'+item.title+'</a></li>';
$compile(searchHTML)($scope);
$scope.setMarkerToCenterA = function() {
alert("this alert is not calling");
}
});
}]);
I have injected the dependencies also.Can anyone tell why ng-click is not calling function even though i am using $compile?
First you need an element where this li element will be located.
<div ng-controller="myController">
<ul id="list"></ul>
</div>
Then in your controller:
var element = angular.element("#list");
element.html($compile(html)($scope));
$scope.setMarkerToCenterA = function() {
alert("Here");
};
Probably you missed to parse the HTML string using angular.element(htmlString) which is then compiled.
var app = angular.module('stackoverflow', []);
app.controller('MainCtrl', function($scope, $compile, $sce) {
var searchHTML = 'hello';
var template = angular.element(searchHTML);
$compile(template)($scope);
angular.element(document.querySelector('#container')).append(template);
$scope.setMarkerToCenterA = function() {
alert("this alert is now calling");
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.9/angular.min.js"></script>
<div ng-app="stackoverflow" ng-controller="MainCtrl">
<div id="container"></div>
</div>

How to observe property changes with dom-bind

How to observe property changes if I use dom-bind? The change in property is updated inside curly brackets, so I assume that there is some event related to change, but I don't know it's name.
Example:
<!doctype html>
<html lang="">
<head >
<link rel="import" href="bower_components/polymer/polymer.html">
<script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script>
<style>
</style>
</head>
<body>
<template is="dom-bind" id="app2">
<p>test: <span>{{test}}</span></p>
<input type="button" value="Change" on-click="chTest">
</template>
<script>
(function (document) {
'use strict';
var app = document.querySelector('#app2');
app.test = "original value";
app.addEventListener('test-changed', function () {
console.log('change listener fired');
});
app.addEventListener('dom-change', function () {
console.log("dom-change");
});
app.chTest = function () {
console.log('click');
app.test = "new value";
// notifyPath-setter will fire "test-changed"-event
// app.notifyPath("test", "notify value");
};
})(document);
</script>
</body>
</html>
EDIT:
There is a need to clarify my question: I want to invoke some function, when app.test changes.
You have the answer commented out. Comment the line app.test and uncomment the app.notifyPath
// app.test = "new value";
// notifyPath-setter will fire "test-changed"-event
app.notifyPath("test", "notify value");
Working jsbin below:
http://jsbin.com/vaqosi/edit?html,console,output
Edit: One workaround is to two way bind it into a child element and listen for its changes. I have updated the jsbin.

Angular does not update UI for keyboard event

I want to update page for keyboard event.
I wired the keyboard event through $window.document.onkeydown. (I know this is not good but it is supposed to work)
However, I find that the page is not updating even the model is changed!
Where am I missing ?
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script>
function Main ($scope, $window) {
$scope.keyCode = 0;
$window.document.onkeydown = function (event) {
$scope.keyCode = event.keyCode;
console.log($scope.keyCode); //the model is changed here
};
}
</script>
</head>
<body ng-app>
<div ng-controller="Main">
{{keyCode}}
</div>
<script type="text/javascript" src="bower_components/angular/angular.js"></script>
</body>
</html>
---Edit---
Here is the code snippet you can try
http://plnkr.co/edit/DFUfHzQPla031IEDdCo3?p=preview
Whenever you want to execute an expression that is outside Angular's scope you need to let Angular know that a change has been made so it can perform a proper digest cycle. You can do this using the $scope.$apply() method. So your example becomes:
function Main ($scope, $window) {
$scope.keyCode = 0;
$window.document.onkeydown = function (event) {
$scope.$apply(function () {
$scope.keyCode = event.keyCode;
console.log($scope.keyCode);
});
};
}
Please see updated plunker here

Angular - append html through different frames with one module per frame

My code have the main windonw and one iframe and each one with your module. A button in main window fires click event that should append html into iframe, the new html when appended into that should apply interceptors and directives properly, but it doesn't work!
Angular javascript:
angular.module('module1',[]).controller('Controller1', function ($scope) {
$scope.get = function(){
$http.jsonp("some_url_here").success(function(html){
$scope.content = html;
});
}
}).directive('click', function($compile) {
return {
link: function link(scope, element, attrs) {
element.bind('click',function(){
var unbind = scope.$watch(scope.content, function() {
var div=document.getElementById("frame").contentWindow.angular.element("divId");
div.append($compile(scope.content)(div.scope()));
unbind();
});
});
}
}
});
angular.module('module2',[]).directive('a', function() {
return {
restrict:'E',
link: function(scope, element, attrs) {
console.log('ping!');
console.log(attrs.href);
}
};
});
Html code:
<html ng-app="modile1">
<div ng-controller="Controller1">
<button type="button", ng-click="get('any_value')", click:""/> Load frame
</div>
<iframe id="frame" src="/please/ignore/this">
<!-- considere the html as appended from iframe-src and contains ng-app="module2" -->
<html ng-app="module2">
<div id="divId">
<!-- code should be inject here -->
</div>
</html>
</iframe>
</html>
Please, considere that angularjs, jquery if applicable, modules-declaration as well as headers are loaded properly.
I'd like to load the html content from main-frame/window into iframe and run interceptors and directives properly. Is it possible? If yes, how can I do it?
Thanks for advancing!
I've tried this code and it seems work fine! I found it here: http://www.snip2code.com/Snippet/50430/Angular-Bootstrap
var $rootElement = angular.element(document.getElementById("frame").contentWindow.document);
var modules = [
'ng',
'module2',
function($provide) {
$provide.value('$rootElement', $rootElement)
}
];
var $injector = angular.injector(modules);
var $compile = $injector.get('$compile');
$rootElement.find("div#divId").append(scope.content);
var compositeLinkFn = $compile($rootElement);
var $rootScope = $injector.get('$rootScope');
compositeLinkFn($rootScope);
$rootScope.$apply();