form has both a `name` attribute and a `ng-controller` directive? - angularjs

I understand that a form directive is an instance of FormController and is published onto the current scope under the value of the name attribute. (https://docs.angularjs.org/guide/forms).
What happens then when a form directive also contains a ng-controller directive as shown in this example?
I tried to see what would happen if the name of the ng-controller attribute is not "FormController":
<html>
<head>
<script src='angular.js'></script>
</head>
<script type='text/javascript'>
Object.prototype.getName = function() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec((this).constructor.toString());
return (results && results.length > 1) ? results[1] : "";
};
</script>
<body>
<div ng-app='theApp'>
<form name='myForm' >
</form>
{{myForm.getName()}}
<form name='myForm2' ng-controller='MyFormController'>
{{myForm2.getName()}}
</form>
</div>
<script type='text/javascript'>
angular.module('theApp', []).controller('MyFormController', ['$scope', function($scope) {}]);
</script>
</body>
</html>
The above code prints in the console:
FormController
FormController

The name of the controller is not important!
The sense of ngForm is that a <form> automatically becomes an instance of the ngForm directive, to which you can attach any controller!
So in the end your myForm2 will have:
ngForm methods and props (es. myForm2.$valid ecc.)
MyFormController methods and props (in your case... nothing :-p )

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>

Angular JS two way binding not updating when using button

I'm a bit of a newb at angular and having a persnickety issue. I am trying to update a variable bound to a div in my controller with a function, that is called when a button is clicked. (The function is bound to the button by ng-click.) When I click the button, the displayed value does not change, even though the variable is changed. However if I assign the same updating function to the element itself it does change when I click that element. Can anyone explain?
Here's my code:
Javascript
angular.module('Compendium',['ngRoute'])
.config(function($routeProvider){
$routeProvider.when('/css',{
templateUrl:'css.html',
controller: 'cssCtrl'
})
}).controller('cssCtrl',function($scope,counterhelper){
//counterhelper($scope.data)
//counter.increment();
$scope.increment = function(){
alert('hey');
$scope.display = 'Nothing'
}
$scope.display = 1;
// var transform = function(){
//
}).factory('counterhelper',function(){
var addOne = function(val){
val ++;
}
return addOne;
})
and Html
<html ng-app = "Compendium">
<head>
<script src = "node_modules/angular/angular.js"> </script>
<script src = "node_modules/angular-route/angular-route.js"> </script>
<script src = "app.js"></script>
<script type="text/ng-template" id="css.html">
<h1 ng-controller = 'cssCtrl' ng-click='increment()'>
{{display}}
</h1>
<button ng-click = 'increment()' >Increment</button>
</script>
</head>
<body>
<div ng-view>
</div>
</body>
</html>
Thanks!
Problem here is your controller is outside the button hence it does not recognize the controller attached, wrap it inside a div
<div ng-controller = 'cssCtrl'>
<h1 ng-click='increment()'>
{{display}}
</h1>
<button ng-click = 'increment()' >Increment</button>
</div>

Angularjs href attribute remove if value is mailto:email

I need to show link in page having attribute value mailto.
normal href attribute value working fine but if value is email than it removed
Code:
myCtrl.link = '<code>Email</code>';
<code><span ng-bind-html="myCtrl.link"></span></code>
rendered output:
<code><a target="_blank">Email</a></code>
Please suggest how to handle anchor having href value like mailto:sulok#atlogys.com
You are running into a "security" issue,
please have a look at this doc-page...
Just say "this is safe" to angular:
function TestCtrl(vm, $sce) {
'use strict';
var htmlString = '<code>Email</code>';
vm.link = $sce.trustAsHtml(htmlString);
}
angular
.module('test', [])
.controller('TestCtrl', ['$scope', '$sce', TestCtrl])
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<article ng-app="test">
<div ng-controller="TestCtrl">
<code><span ng-bind="link"></span></code>
</div>
</article>

How to $watch multiples properties simultaneous and interpolate into one expression?

Suppose two input fields - name and text. How to simultaneous watch this two fields and interpolate their value into one expression?
Thanks!
Update 9/7/2014:
I did this Plunkr with a working version of the code :)
Thanks Mohammad Sepahvand!
Code:
<!doctype html>
<html ng-app="myApp">
<head>
<title>Interpolate String Template Example</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.js"></script>
<script type="text/javascript">
angular.module('myApp', ['emailParser']).controller('MyController', ['$scope', 'EmailParser', function ($scope, EmailParser) {
// init
$scope.to = '';
$scope.emailBody = '';
$scope.$watchCollection('[to, emailBody]', function (newValues, oldValues) {
// do stuff here
// newValues and oldValues contain the new and respectively old value
// of the observed collection array
if (newValues[0] && newValues[1]) { // there's name and some text?
$scope.previewText = EmailParser.parse(newValues[1], {to: $scope.to});
}
});
}]);
angular.module('emailParser', []).config(['$interpolateProvider', function ($interpolateProvider) {
$interpolateProvider.startSymbol('__');
$interpolateProvider.endSymbol('__');
}]).factory('EmailParser', ['$interpolate', function ($interpolate) { // create service
return {
parse: function (text, propertiesToBeInterpolated) { // handle parsing
var template = $interpolate(text);
return template(propertiesToBeInterpolated);
}
};
}]);
</script>
</head>
<body>
<h3>Instructions in readme.md file - please read before!</h3>
<div id="emailEditor" ng-controller="MyController">
<label>*Name:</label>
<input ng-model="to" type="text" placeholder="Ex.: John"/>
<br><br>
<label>*Text:</label><br>
<textarea ng-model="emailBody" cols="25" rows="10" placeholder="Write something"></textarea>
<p style="color:red;">*required</p>
<div>
<pre>__previewText__</pre>
</div>
</div>
</body>
</html>
You can use the $watchGroup method that was added in angular 1.3:
$scope.$watchGroup(['prop1', 'prop2'], function(newValues, oldValues, scope) {
var prop1 =newValues[0];
var prop2 =newValues[1];
});
Or you could use $watchCollection which has been available since angular 1.1.4:
scope.$watchCollection('[prop1, prop2]', function(newValues, oldValues){
});

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