how to call controller function from template in angularjs - angularjs

I am creating an html from controller and appending this html to included html file in template view. but I am unable to call controller function from there when i am clicking on checkbox. I want to get all those values in that function.
This is my test html code:-
<div ng-app>
<div ng-controller="TodoCtrl">
<div id="priceappend"></div> <!-- This div I am using in included html say test1.html -->
<!-- I cannot iterate array over here, As I am appending priceHtml into test1.html which I am including using ng-include -->
</div>
</div>
and this is my controller js code:-
function TodoCtrl($scope,$window) {
$scope.pricerangelist = {
chkbox1:{selected:false,id:'below100',minvalue:'0',maxvalue:'100'},
chkbox2:{selected:false,id:'below400',minvalue:'100',maxvalue:'400'},
};
var priceHtml = '';
priceHtml +='<div class="ui-checkbox ui-checkbox-row"><label for="below100" class="ui-btn ui-corner-all ui-btn-d ui-btn-icon-left">100 and below</label><input type="checkbox" min_value="0" max_value="100" value="100 US$ and below" class="range myinput large custom" ng-change="pricelistAction(pricerangelist)" ng-model="pricerangelist.chkbox1.selected" name="range[]" id="below100"></div>';
priceHtml += '<div class="ui-checkbox ui-checkbox-row"><label for="below400" class="ui-btn ui-corner-all ui-btn-d ui-btn-icon-left">101 and 400</label><input type="checkbox" min_value="101" max_value="400" value="101 US$ and 400 US$" class="range myinput large custom" ng-change="pricelistAction(pricerangelist)" ng-model="pricerangelist.chkbox2.selected" name="range[]" id="below400"></div>';
var myEl = angular.element( document.querySelector( '#priceappend' ) );
myEl.append(priceHtml);
$scope.pricelistAction = function(val){
console.log(val);
//this function is not calling.
};
}
here is the plnkr

You need to compile the newly created HTML so as to use scope.
so replace myEl.append(priceHtml); with myEl.append($compile(priceHtml)($scope));
http://jsfiddle.net/U3pVM/23071/

Add $complie to your controller like this function TodoCtrl($scope,$window, $compile)
Now before appending the html string call $compile, so that the functions in the template string can be bound to $scope.
myEl.append($compile(priceHtml)($scope))

Related

angularjs dom manipulation based on button click

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>

angularjs to output html clickable element instead of html as a string

I am using a filter to convert any URL or email id from a piece of content. but its getting rendered as a string not as a clickable HTML element.
Filter JS
angular.module('myApp.filters', []).filter('parseUrl', function() {
var urls = /(\b(https?|ftp):\/\/[A-Z0-9+&##\/%?=~_|!:,.;-]*[-A-Z0-9+&##\/%=~_|])/gim
var emails = /(\w+#[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim
return function(text) {
if (text.match(urls)) {
text = text.replace(urls, "$1")
}
if (text.match(emails)) {
text = text.replace(emails, "$1")
}
return text
}
});
this above code output me with a plane text and not clickable HTML elements.
Fiddle
I have updated JS Fidle
HTML:
Added
ng-bind-html
<div ng-app="miniapp">
<div ng-controller="Ctrl">
<h1 ng-bind-html="test | parseUrl">{{test}}</h1>
</div>
</div>
Documentation ngBindHtml
Your filter should make use of the Strict Contextual Escaping $sce to return trusted HTML
angular.module('myApp.filters', []).filter('parseUrl', function ($sce) {
var urls = /(\b(https?|ftp):\/\/[A-Z0-9+&##\/%?=~_|!:,.;-]*[-A-Z0-9+&##\/%=~_|])/gim
var emails = /(\w+#[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim
return function (text) {
if (text.match(urls)) {
text = text.replace(urls, "<a ng-href=\"$1\" target=\"_blank\">$1</a>");
}
if (text.match(emails)) {
text = text.replace(emails, "<a ng-href=\"mailto:$1\">$1</a>");
}
return $sce.trustAsHtml(text);
}
});
Update
It seems your are using an older version of Angular (version 1.0.2) which doesn't have the Strict Contextual Escaping $sce. That explains your usage of ngSanitize module.
Your filter code is correct, but you should bind your text differently using the ng-bind-html.
<div ng-app="miniapp">
<div ng-controller="Ctrl">
<h1 ng-bind-html="test | parseUrl"></h1>
</div>
</div>
JsFiddle : http://jsfiddle.net/fb4meygo/1/
With the help of linky filter we can detect links from text and show them differently. Linky takes text and produces HTML by wrapping all URLs into anchor tags. It supports email address, http, https, and mailto.
HTML:
<div ng-app="myApp" ng-controller="myController">
<div>
<p ng-bind-html="myText | linky :'_blank'"></p>
<textarea ng-model="myText" style="width: 420px; height: 120px"></textarea>
</div>
</div>
Controller:
var myApp = angular.module('myApp', ['ngSanitize'])
.controller('myController', ['$scope', function ($scope) {
$scope.myText = "Some default text is here http:/tothenew.com/";
}]);

generate dynamic html on ng click

I want to insert dynamic html element which contains ng-bind and directive on ng-click. I want to insert new html elements inside
Html looks like this
<body data-ng-controller="controller">
<div id="toolbox">
<label>Page Width</label>
<input type="text" data-ng-model="pageWidth" />
<input type="button" value="H1" data-ng-click="createH1()" />
</div>
<div id="editor">
<div data-ng-style="{width:pageWidth + 'px'}" data-ng-page>
</div>
</div>
</body>
Controller >
app.controller('controller', ['$scope', function ($scope) {
$scope.createH1 = function () {
document.getElementById("page").innerHTML = document.getElementById("page").innerHTML + ("<div class='h1' data-ng-h1 draggable></div>");
};
}]);
The above controller is inserting html element, but the directives of new html elements are not working.
However I came to know that unless we $compile template/html they'll not work. If I use app.directive( ngPage, ..) to add my dynamic html, it is inserting while app is started. But I want to insert only on button ng-click.
I'm new to angular js, a bit confused please help me out with this.
Thanks in advance.
I will Always prefer to do DOM manipulation from directive. So here code will look like below
HTML
<body ng-controller="MainCtrl as vm">
<button add-html>click me</button>
<div id="page">
This will be replaced by text
</div>
</body>
CODE
app.directive('addHtml', function($compile){
return {
restrict: 'AE',
link: function(scope, element, attrs){
var html = `<div class='h1' data-ng-h1 draggable>Test</div>`,
compiledElement = $compile(html)(scope);
element.on('click', function(event){
var pageElement = angular.element(document.getElementById("page"));
pageElement.empty()
pageElement.append(compiledElement);
})
}
}
});
Plunkr Here

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

How to set repeated element id in AngularJS?

I'd like to do something like:
<div class='row' ng-repeat='row in _.range(0,12)'>
<div id='{{row}}'></div>
</div>
but when in the controller I try:
function SetterForCatanCtrl($scope) {
$scope._ = _;
try {
var tile = document.getElementById('5');
tile.style.backgroundImage = "url('aoeu.png')";
} catch (e) {
alert(e)
}
}
getElementById returns null so how can an element's id be set using AngularJS variables?
The function SetterForCatanCtrl is run only once, when angular encounters a ngController directive while it bootstraps your app. When this happens the element you want to access from the DOM doesn't exist yet.
Doing DOM manipulation from a controller is not a good practice, directives are can solve the kind of problem you are facing. Your use case can be solved with CSS and just switching classes but I guess you want to do more than just setting a background image.
DOM manipulation from a controller
You are not asking for custom directives, so a quick solution could done using the ngClick directive and call a method that can switch images
Example HTML
<div ng-controller='ctrl'>
<div class='row' ng-repeat='row in _.range(0,12)'>
<div id='{{row}}' ng-click="click($index)">
<button>{{row}}</button>
</div>
</div>
</div>
And JS
var App = angular.module('app', []);
App.run(function($rootScope) {
$rootScope._ = _;
});
App.controller('ctrl', function($scope){
$scope.click = function(idx){
var elem = document.getElementById(idx);
console.log('clicked row', idx, elem);
};
​}); ​
So when a button is clicked you will get an id and use it to get an element from the DOM. But let me repeat, a for this use case a directive is a better choice.
JSFiddle: http://jsfiddle.net/jaimem/3Cm2Y/
pd: if you load jQuery you can use angular.element(<selector>) to select elements from the DOM.
edit: adding directive example
DOM manipulation from a directive
Using a directive is simpler, since you can just bind an event to the element the directive is applied to
HTML
<h1>Directive</h1>
<div class='row' ng-repeat='row in _.range(0,12)'>
<div id='{{row}}' my-directive>
<button>{{row}}</button>
</div>
</div>
JS
App.directive('myDirective', function(){
return function(scope, element, attr){
element.bind('click', function(){
console.log('clicked element: ', element, element.html());
});
};
});
http://jsfiddle.net/jaimem/3Cm2Y/1/

Resources