angularjs dom manipulation based on button click - angularjs

basically i want to change the attribute value based on the button i clicked,
these are the two buttons
<button ng-click="fn(a)"></button>
<button ng-click="fn(b)"></button>
and then i have a prebuilt directive who takes value as input,
<div directive-name="" id="abc"></div>
if i click on first button,i want the value of directive based on button clicked.
What i did earlier;
$scope.go = function(data){
if(data==a){
var b = document.querySelector( 'div' );
b.setAttribute("directive-name","value");
}
else{}
}
here the problem is that it is selecting the first div of document and setting attribute value for that.
I also tried to pass it with id like
var b = angular.element(document.querySelector('#abc'));
I also saw some custom directives to do so, but they are not working
AngularJS DOM Manipulation through Directives
If possible provide me a demo in plunkr or fiddle
and also if i want to change css property of div based on button clicked
Thanks in advance

You can do it like this.
Assign the directive-name value to a $scope.variable and then use variable as the value in HTML.
HTML - 1:
<button ng-click="go(a)"></button>
<button ng-click="go(b)"></button>
HTML - 2:
<div directive-name="{{directive}}" id="abc"></div>
JS:
$scope.go = function(data){
if(data==a){
$scope.directive = "directive-1";
}else if(data==b){
$scope.directive = "directive-2";
}
}
To assign class name to div you can define other $scope.classVar and then use that in HTML like below:
<div directive-name="{{directive}}" id="abc" ng-class="classVar"></div>
I hope this will solve your problem.

This should work, (you had some errors in your code):-
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.fn = function(data,id) {
if (data == 'a') {
var b = document.querySelector('#'+id);
b.setAttribute("directive-name", "value");
} else {
}
}
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<div directive-name="" id="abc"></div>
<button ng-click="fn('a','abc')">A</button>
</div>

"Basically I want to change the attribute value based on the button I clicked."
You can do this by changing the attribute value the angular way, referencing a property of $scope or the controller instance in your template. When clicking a button, set the variable to the value you require to be passed to your directive.
Note: When you pass a value into your ngClick directive, you need to pass it as a string unless a and b are declared as properties of $scope.
Here's a basic example:
// app.js
(function() {
'use strict';
angular.module('app', []);
})();
// main.controller.js
(function() {
'use strict';
angular.module('app').controller('MainController', MainController);
MainController.$inject = ['$scope'];
function MainController($scope) {
$scope.fn = fn;
function fn(data) {
// set the value so it's accessable in the view
// therefore we can pass it into our directive
$scope.myVar = data;
}
}
})();
// directive-name.directive.js
(function() {
'use strict';
angular.module('app').directive('directiveName', directiveNameDirective);
function directiveNameDirective() {
return {
restrict: 'A',
scope: {
directiveName: '='
},
template: '<span>directiveName: {{ directiveName }}</span>'
};
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="MainController as MainCtrl">
<!-- here we pass a and b as strings otherwise they get evaluated as variables -->
<button ng-click="fn('a')">Set a</button>
<button ng-click="fn('b')">Set b</button>
<hr>
<!-- here we pass myVar which is declared as a property of $scope when the fn function is called -->
<div directive-name="myVar" id="abc"></div>
<hr> myVar: {{ myVar }}
</div>
</div>

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

Angular 1.5 Pass data from component to controller

I have component inside of the controller and i'm binding the data to it. How to make changes in component visible in the controller.
I have that code:
JS
app.controller('TheCtrl', function($scope) {
$scope.changeable = 'earlier';
});
app.component('innerComponent', {
bindings: {
changeable: '='
},
controller: function() {
this.changeable = 'later';
}
}
HTML
<div ng-controller="TheCtrl">
<inner-component changeable="val"></inner-component>
<p>
{{changeable}}
</p>
</div>
And it doesn't change the 'changeable' value in the view of the controller (it show "earlier" value). Why? How to make the changes visible in the controller?
It does work as expected.
function appCtrl() {
this.value = "test";
}
var inner = {
bindings: {
changeable: '='
},
controller: function() {
this.changeable = 'later';
}
};
angular.module('app', []);
angular.module('app')
.controller('appCtrl', appCtrl)
.component('inner', inner);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="appCtrl as ctrl">
<inner changeable="ctrl.value"></inner>
<p>
{{ctrl.value}}
</p>
</div>
</div>
However you shouldn't use components for building MVW apps.
You either go all the way and create a component root with children components or use "controlled divs".
But hybrid MVC/components apps are bad architecture.

Angular directive controller scope visibility

Question
Why isn't monkey and selected visible to the template?
Plunk
http://plnkr.co/edit/djS0KWyfJNKD0tfZ0IiV?p=preview
Code
<head>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.3/angular.js"></script>
<script type="text/javascript">
angular
.module('toruSelect', [])
.directive('toruSelect', function () {
return {
restrict: 'AE', // Allow usage as A - attribute, E - element
scope: { // Isolated scope
selected: '=' // Bi-directional binding to selected attribute,
},
controller: ['$scope', function ($scope) {
$scope.monkey = 'MONKEY';
console.log('toruSelect.controller.$scope', $scope);
}]
}
});
var app = angular.module('app', ['toruSelect']);
app.controller('AppCtrl', function($scope) {
$scope.val = 'initial';
$scope.appData = 'App data';
});
</script>
</head>
<body ng-controller="AppCtrl">
<h1>Directives and scopes..</h1>
<div toru-select selected="val">
<div style="color: red">RESULT: toruSelect.controller.monkey: {{monkey}}</div>
<div>EXPECTED: toruSelect.controller.monkey: MONKEY</div>
<div style="color: red">RESULT: toruSelect.controller.selected: {{selected}}</div>
<div>EXPECTED: toruSelect.controller.selected: initial</div>
</div>
</body>
Result
Directives and scopes..
RESULT: toruSelect.controller.monkey:
EXPECTED: toruSelect.controller.monkey: MONKEY
RESULT: toruSelect.controller.selected:
EXPECTED: toruSelect.controller.selected: initial
As you pointed it out on the comment of your directive, it has an isolated scope, so that value attached with monkey key is available on directive scope, not on controller one.
For selected, you have to display {{val}} and not {{selected}} as it's the variable concerned by the bi-directional binding on the directive scope.

Why isn't the Angular ng-click event firing?

I've been following a course to learn angularjs and I can't seem to get a simple ng-click binding to work.
HTML:
<body ng-controller="MainController">
<div ng-app="githubViewer">
<h1>{{message}}</h1>
<div>{{ error }}</div>
{{username}}
<form name="searchUser">
<input type="search" placeholder="Username to find" ng-model="username" />
<input type="submit" value="Search" ng-click="search(username)" />
</form>
<div>
<div>{{user.name}}</div>
<img ng-src="http://www.gravatar.com/avatar/{{user.gravatar_id}}" title="{{user.name}}">
{{user.gravatar_id}}
</div>
</div>
</body>
Javascript:
(function () {
var module = angular.module("githubViewer", []);
var MainController = function ($scope, $http) {
var onUserComplete = function (response) {
$scope.user = response.data;
};
var onError = function (reason) {
$scope.error = "Could not fetch the user";
$scope.reason = reason;
};
$scope.username = "angular";
$scope.message = "Github Viewer";
$scope.search = function (username) {
$http.get("https://api.github.com/users/" + username)
.then(onUserComplete, onError);
};
};
module.controller("MainController", MainController);
}());
When you click the search button (search for username "odetocode" or "robconery") it is supposed to display an image but the click event does not seem to be firing. I have searched the documentation and looked over the course again but I can't see what I'm doing wrong.
I'm currently using version 1.2.16 of angularjs.
You have the ng-controller declaration outside of the ng-app declaration right now:
<body ng-controller="MainController">
<div ng-app="githubViewer">
It should be the other way around, or have both on the same element
<body ng-app="githubViewer" ng-controller="MainController">
<div>
AngularJS evaluates your code, and checks for any directives you have declared from the ng-app element down, including the element it is declared on; This currently is missing the ng-controller directive, as it is placed on a parent element of the ng-app element.
You need to put the controller within the context of the module to have it within its scope.
Like so
<body ng-app="githubViewer" ng-controller="MainController">
Demo here

Resources