How to apped a `directive` by click - angularjs

Say, I have multiple directives, on click how can i add the "directive" what i want to "popup". i have number of scenario, but using only one pop-up for all. whenever the appropiate element is clicked, using the same pop-up, i would like to update the other 'directives'
for sample, i created only one. click on the red bordered title
here is my code :
<div ng-controller="main">
{{name}}
<div class="info" ng-click="popIt()">
<info-board></info-board>
</div>
<div class="popup" ng-if="show" ng-click="popIt()">
//add directive dynamically - how?
</div>
</div>
</body>
<script type="text/ng-template" id="modalPopup.html">
<div class='ng-modal'>
some information here.
</div>
</script>
js:
var myApp = angular.module("myApp", []);
myApp.controller("main", function($scope) {
$scope.name = "Mo!";
$scope.show = false;
$scope.popIt = function (show) {
$scope.show = !$scope.show;
}
})
myApp.directive("infoBoard", function() {
return {
replace : true,
templateUrl: "modalPopup.html",
scope : {},
link : function (scope, element, attrs) {
element.append("Hi there!")
}
}
})
Demo Onlie

Related

Adding ng-model directive to dynamically created input tag using AngularJs

I am trying that on a button click, a div and and input tag are created and the input tag contain ng-model and the div has binding with that input.
Kindly suggest some solution.
You can create the div and input beforehand and and do not show it by using ng-if="myVar". On click make the ng-if="true".
<button ng-click="myVar = true">
In controller : $scope.myVar = false;
$scope.addInputBox = function(){
//#myForm id of your form or container boxenter code here
$('#myForm').append('<div><input type="text" name="myfieldname" value="myvalue" ng-model="model-name" /></div>');
}
Here is another solution, in which there's no need to create a div and an input explicitly. Loop through an array of elements with ng-repeat. The advantage is that you will have all the values of the inputs in that array.
angular.module('app', [])
.controller('AppController', AppController);
AppController.$inject = ['$scope'];
function AppController($scope) {
$scope.values = [];
$scope.add = function() {
$scope.values.push('');
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="AppController">
<button ng-click="add()">Click</button>
<div ng-repeat="value in values track by $index">
<input type="text" ng-model="values[$index]"/>
<div>{{values[$index]}}</div>
</div>
<pre>{{values}}</pre>
</div>
UPDATE. And if you want only one input, it's even simpler, using ng-show.
angular.module('app', []);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<button ng-click="show = true">Click</button>
<div ng-show="show">
<input type="text" ng-model="value"/>
<div>{{value}}</div>
</div>
</div>
You should use $compile service to link scope and your template together:
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', '$compile', '$document' , function MyCtrl($scope, $compile, $document) {
var ctrl = this;
var inputTemplate = '<div><span ng-bind="$ctrl.testModel"></span>--<span>{{$ctrl.testModel}}</span><input type="text" name="testModel"/></div>';
ctrl.addControllDynamically = addControllDynamically;
var id = 0;
function addControllDynamically() {
var name = "testModel_" + id;
var cloned = angular.element(inputTemplate.replace(/testModel/g, name)).clone();
cloned.find('input').attr("ng-model", "$ctrl." + name); //add ng-model attribute
$document.find('[ng-app]').append($compile(cloned)($scope)); //compile and append
id++;
}
return ctrl;
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.angularjs.org/1.6.2/angular.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl as $ctrl">
<input type="button" value="Add control dynamically" ng-click="$ctrl.addControllDynamically()"/>
</div>
</div>
UPDATE: to add a new compiled template each time the button is clicked, we need to make a clone of the element.
UPDATE 2: The example above represents a dirty-way of manipulating the DOM from controller, which should be avoided. A better (angular-)way to solve the problem - is to create a directive with custom template and use it together with ng-repeat like this:
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', function MyCtrl($scope) {
var ctrl = this;
ctrl.controls = [];
ctrl.addControllDynamically = addControllDynamically;
ctrl.removeControl = removeControl;
function addControllDynamically() {
//adding control to controls array
ctrl.controls.push({ type: 'text' });
}
function removeControl(i) {
//removing controls from array
ctrl.controls.splice(i, 1);
}
return ctrl;
}])
.directive('controlTemplate', [function () {
var controlTemplate = {
restrict: 'E',
scope: {
type: '<',
ngModel: '='
},
template: "<div>" +
"<div><span ng-bind='ngModel'></span><input type='type' ng-model='ngModel'/></div>" +
"</div>"
}
return controlTemplate;
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.angularjs.org/1.6.2/angular.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl as $ctrl">
<input type="button" value="Add control dynamically" ng-click="$ctrl.addControllDynamically()"/>
<div ng-repeat="control in $ctrl.controls">
<control-template type="control.type" ng-model="control.value"></control-template>
</div>
</div>
</div>

controller arguments should change text

$scope.man="A"; //default text
<div ng-app="myApp" ng-controller="myCtrl">
<p>person clicked {{man}}</p>
<button ng-click="man('b')">B</button><br>
<button ng-click="man('c')">C</button>
</div>
var app=angular.module("myApp",[]);
app.controller("myCtrl",function($scope){
$scope.man="A";
$scope.man=function(value)
{
$scope.man=value;
}
});
i am new to angularjs i wanted to change text by arguments but text is not changing and the default text A is also not getting displayed can some one help me out with this
check this link
https://jsfiddle.net/nikhila/31gz56tn/
Your $scope variable and function are same. Change your function like this,
HTML:
<div ng-app="myApp" ng-controller="myCtrl">
<p>person clicked {{man}}</p>
<button ng-click="change('b')">B</button><br>
<button ng-click="change('c')">C</button>
</div>
Controller:
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.man = "A";
$scope.change = function(value) {
$scope.man = value;
}
});
DEMO

Get event information using angularjs

I am trying to track button clicks a user performs on a page/view. I am trying to get the element idwhich was clicked.
Is there a way to do this without having to tie a function or directive to each element?
ng-controller and ng-click
HTML:
<body ng-controller="MyController" ng-click="go($event)">
<div id="box1">
<div id="box2">
<div id="box3"></div>
</div>
</div>
</body>
JS:
$scope.go = function(e) {
var clickedElement = e.target;
console.log(clickedElement);
console.log(clickedElement.id);
};
Demo: http://plnkr.co/edit/1O6pCVrvgu7Bl8b6TlPF?p=preview
Directive:
HTML:
<body my-directive>
<div id="box1">
<div id="box2">
<div id="box3"></div>
</div>
</div>
</body>
JS:
app.directive('myDirective', function () {
return {
link: function (scope, element, attrs) {
element.bind('click', function (e) {
var clickedElement = e.target;
console.log(clickedElement);
console.log(clickedElement.id);
});
}
}
});
Demo: http://plnkr.co/edit/eevnMFu2YBj3QqRraeZh?p=preview

Can not reflect changes in model

I have an AngularJS controller like this
var myModule = angular.module('test', []);
myModule.controller('PendataanMainController',
function($scope, $http)
{
$scope.stat1 = "";
$scope.stat2 = "stat2";
$scope.AmbilStat1 = function()
{
$scope.stat1 = "Hallo stat1";
};
$scope.AmbilStat2 = function()
{
$scope.stat2 = "Hallo stat2";
}
}
);
myModule
.directive(
'fonloaded',
function()
{
return {
restrict: 'A',
link: function(scope, element, attrs)
{
var this_element = angular.element(element);
this_element.bind(
'click',
function()
{
//this_element.html('<h2>Hallo dari directive</h2>');
scope.stat1 = "Hallo dari directive";
}
);
scope.$apply();
}
}
}
);
and a HTML like this
<div ng-app="test" ng-controller="PendataanMainController" class="columns clear bt-space15">
<div class="col1-2 fl-space2">
<div class="content-box">
<div class="box-body">
<div fonloaded class="box-header clear">
<h2>{{stat1}}</h2>
</div>
{{AmbilStat2()}}
<div class="box-wrap clear">
{{stat2}}
</div>
</div>
</div>
</div>
<div class="col1-2 lastcol">
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<h2>Stat 2</h2>
</div>
<div class="box-wrap clear">
{{stat2}}
</div>
</div>
</div>
</div>
</div>
I made a custom directive 'fonloaded' and put it on this part:
<div fonloaded class="box-header clear">
<h2>{{stat1}}</h2>
</div>
and when it got clicked, the directive link function change the value of stat1. I want that new stat1 reflected in the html. But it don't.
I am using AngularJS extension for Chrome. And I can see that the stat1 value has changed, but that change does not reflected on the html.
What would be the problem?
http://plnkr.co/edit/4kiJwrG8Xo0unrNc9Fw7?p=preview
please see fixed sample:
function()
{
return {
restrict: 'A',
link: function(scope, element, attrs)
{
var this_element = angular.element(element);
this_element.on('click',
function(e)
{
// alert('1');
//this_element.html('<h2>Hallo dari directive</h2>');
scope.stat1 = "Hallo dari directive";
scope.$apply();
} );
}
}
}
I must add that I am working within a HTML template (like one from theme forest). I have stripped the ng-app part out of the HTML template to make it stand alone. And now it reflect the changes in the model.
Somehow the HTML template using jQuery to modify the tag which has fonloaded directive. As result {{stat1}} lost by HTML template transformation.

What is the *Angular* way to get an elements siblings?

What is the idiomatic way to get an elements siblings when it is clicked using AngularJS?
So far I've got this:
<div ng-controller="FooCtrl">
<div ng-click="clicked()">One</div>
<div ng-click="clicked()">Two</div>
<div ng-click="clicked()">Three</div>
</div>
<script>
function FooCtrl($scope){
$scope.clicked = function()
{
console.log("Clicked", this, arguments);
};
}
</script>
here's a jQuery implementation as a concrete example:
<div id="foo">
<div>One</div>
<div>two</div>
<div>three</div>
</div>
<script>
$(function(){
$('#foo div').on('click', function(){
$(this).siblings('div').removeClass('clicked');
$(this).addClass('clicked');
});
});
</script>
Use a directive, since you want to traverse the DOM:
app.directive('sibs', function() {
return {
link: function(scope, element, attrs) {
element.bind('click', function() {
element.parent().children().removeClass('clicked');
element.addClass('clicked');
})
},
}
});
<div sibs>One</div>
<div sibs>Two</div>
<div sibs>Three</div>
Note that jQuery is not required.
fiddle
Here is an angular version of the jQuery sample that you provided:
HTML:
<div ng-controller="FooCtrl">
<div ng-click="selected.item='One'"
ng-class="{clicked:selected.item=='One'}">One</div>
<div ng-click="selected.item='Two'"
ng-class="{clicked:selected.item=='Two'}">Two</div>
<div ng-click="selected.item='Three'"
ng-class="{clicked:selected.item=='Three'}">Three</div>
</div>
JS:
function FooCtrl($scope, $rootScope) {
$scope.selected = {
item:""
}
}
NOTE: You dont strictly need to access DOM for this. However if you still want to then you can write a simple directive. Something like below:
HTML:
<div ng-controller="FooCtrl">
<div ng-click="clicked()" get-siblings>One</div>
<div ng-click="clicked()" get-siblings>Two</div>
<div ng-click="clicked()" get-siblings>Three</div>
</div>
JS:
yourApp.directive('getSiblings', function() {
return {
scope: true,
link: function(scope,element,attrs){
scope.clicked = function () {
element.siblings('div').removeClass('clicked');
element.addClass('clicked');
}
}
}
});
fiddle
Following is a directive built exclusively with Angular grammar (borrowing from jqLite):
link: function(scope, iElement, iAttributes, controllers) {
var parentChildren,
mySiblings = [];
// add a marker to this element to distinguish it from its siblings
// this could be a lot more robust
iElement.attr('rsFindMySiblings', 'anchor');
// get my parent's children, it will include me!
parentChildren = iElement.parent().children();
// remove myself
scope.siblings = [];
for (var i=0; i < parentChildren.length; i++) {
var child = angular.element(parentChildren[i]);
var attr = child.attr('rsFindMySiblings');
if (!attr) {
scope.siblings.push({name: child[0].textContent});
}
}
}
Note that it uses a controller to store the results. See this plunker for a detailed example

Resources