Angularjs select in directive not showing label - angularjs

I have tried and I can't get what is wrong with my directive. I want to encapsulate the select tag in a directive. It seems to work correctly, with one issue: the label in the select statement is not shown. I have presented both, the non-directive and the directive version, in this plunker. Any help would be appreciated.
The javascript:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.colors = [{"label": "blue", value: "1"},
{"label": "red", value: "2"},
{"label": "green", value: "3"}];
$scope.color = $scope.colors[1];
});
app.directive('szpSelect', function() {
function linker(scope, elem, attrs, ctrl) {
}
return {
restrict: 'E',
link: linker,
replace: false,
scope: {
list: "=szpList",
value: "=szpValue"
},
template: '<select ng-model="value" ng-options="o.label for o in {{list}}"></select>'
}
});
The html:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.2.x" src="http://code.angularjs.org/1.2.13/angular.js" data-semver="1.2.13"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
(1)Non-directive: <select ng-model = "color"
ng-options="o.label for o in colors"></select>
</br>
(2) Directive: <szp-select szp-value="color"
szp-list="colors">
</szp-select>
</body>
</html>

You have to remove the brackets in template
template: '<select ng-model="value" ng-options="o.label for o in list"></select>'

Related

How to make a custom ngIf directive without scope isolation

I want to use ngIf directive and to make my custom myOwnIf directive without scope isolation. As you can see in the code here - it doesn't work for me without scope isolation.
Can someone assist in understanding the problem and the solution?
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
});
var MyOwnIf = (function () {
/* #ngInject */
function MyOwnIf($element) {
this.isDisplay = $element.attr('my-own-if') === 'true';
}
return MyOwnIf;
}());
app.directive('myOwnIf', function () { return ({
template: "<div ng-if=\"$ctrl.isDisplay\"><ng-transclude></ng-transclude></div>",
transclude: true,
controller: MyOwnIf,
controllerAs: '$ctrl',
//scope: {}, --> If I will uncomment this it will work, but I don't want to isolate the scope
bindToController: true,
restrict: 'A'
}); });
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.9/angular.js" data-semver="1.4.9"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<div my-own-if="false">This text should NOT show because value is FALSE</div>
<div my-own-if="true">This text should show because I value is TRUE</div>
</body>
</html>

Angularjs generic input directive with integrated validation

I have been trying to write a generic input directive with integrated validation. But I cant seem to get the validation to fire (ng-show).
My guess is I don't really have a grasp on when the items are being evaluated by angular and added to the watch list but I am not sure.
My actual control is more complicated but have created a simplified version to illustrate the issue.
The generated HTML (viewed with inspector) looks like it should work.
What am I missing? Here is the: Plunker Validation Test
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script data-require="angular.js#1.4.7" data-semver="1.4.7" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<form name='myForm'>
<h1>Validation Test</h1>
Name: <my-input uname='userName'></my-input><br>
Phone: <my-input uname='phone'></my-input><br>
</form>
<script>
var app = angular.module('myApp',[]);
app.directive('myInput',function(){
return {
requires: '^form',
replace:true,
scope:{
uname:'='
},
restrict: 'E',
template: function(element,attr){
return '<div><input class="reqclass" ng-model="' + attr.uname + '" name="' + attr.uname + '" ng-minlength="5"></input><span ng-show="myForm.' + attr.uname + '.$error.minlength">Too short!</span></div>'
}
};
});
</script>
</body>
</html>
For anyone else with similar issue.
Thanks for comment, it led me to answer. See revised code below.
Issue was access to form in isolated scope as well as attempting to use form name rather than scope.form object in span.
NOTE the require:['^form','?ngModel'] and in link: scope.form = ctrls[0] and revised ng-show="form.' + attr.uname + '.$error.minlength"
Plunker above has also been revised to reflect correction
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script data-require="angular.js#1.4.7" data-semver="1.4.7" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<form name='form'>
<h1>Validation Test</h1>
Name: <my-input uname='userName'></my-input><br>
Not Directive: <div><input class="reqclass" name="city" ng-model="city" ng-minlength="5"/><span ng-show="form.city.$error.minlength">Too short!</span></div><br>
Phone: <my-input uname='phone'></my-input><br>
</form>
<script>
var app = angular.module('myApp',[]);
app.directive('myInput',function(){
return {
require: ['^form', '?ngModel'],
replace:false,
scope:{
uname:'='
},
restrict: 'E',
template: function(element,attr){
return '<div><input class="reqclass" name="' + attr.uname + '" ng-model="' + attr.uname + '" ng-minlength="5"/><span ng-show="form.' + attr.uname + '.$error.minlength">Too short!</span></div>'
},
link: function(scope, element, attrs, ctrls) {
scope.form = ctrls[0];
var ngModel = ctrls[1];
}
}
});
</script>
</body>
</html>

Watch a custom directives inner html in angular

I have a global search variable that is used by the whole app
newspaper.controller("MainController", function($scope) {
$scope.search = {query:''};
});
Then I have a contenteditable div that I want to bind to $scope.search
app.directive('search', function() {
return {
restrict: 'AE',
replace: true,
template: '<div ng-model="query" id="search"></div>',
scope: {
query: '='
},
controller: function($scope) {
// I want to watch the value of the element
$scope.$watch('query', function(newValue, oldValue){
console.log(newValue);
},true);
},
link: function(scope, element, attrs) {
// Medium JS content editable framework
new Medium({
element: element[0],
mode: Medium.inlineMode
});
}
}
});
The watch is not firing when I type new values into the div, I guess Im still confused on how to link a directive with a model. Here's the HTML
<nav ng-controller="MainControllerr">
<search context="search.query"></np-search>
</nav>
Don't think you need the watch. It's bad practise to use watch functions in your controllers anyway as it makes them really hard to test.
Here's a simplified version of what (I think) your trying to do.
DEMO
index.html
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.2/angular.js" data-semver="1.4.2"></script>
<script src="app.js"></script>
</head>
<body>
<nav ng-controller="MainController">
<pre>{{query}}</pre>
<search query="query"></search>
</nav>
</body>
</html>
app.js
var app = angular.module('plunker', []);
app.controller("MainController", function($scope) {
$scope.query = {value:''};
});
app.directive('search', function() {
return {
restrict: 'AE',
template: '<input ng-model="query.value" id="search"/>',
scope: {
query: '='
}
}
});
EDIT
If you really want to use a content editable div you'd have to try something like this:
Also, see this SO question from which I've taken and adapted code to create the demo below. Hope it helps.
DEMO2
index.html
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.2/angular.js" data-semver="1.4.2"></script>
<script src="app.js"></script>
</head>
<body>
<nav ng-controller="MainController">
<pre>{{query}}</pre>
<div search contenteditable="true" ng-model="query.value">{{ query.value }}</div>
</nav>
</body>
</html>
app.js
var app = angular.module('plunker', []);
app.controller("MainController", function($scope) {
$scope.query = {value:'rrr'};
});
app.directive('search', function() {
return {
restrict: 'AE',
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
element.bind('blur', function() {
scope.$apply(function() {
ctrl.$setViewValue(element.html());
});
});
element.html(ctrl.$viewValue);
}
}
});

How can I set the value of an id in the template part of a directive?

I am trying this:
http://plnkr.co/edit/IzhScWwcy6owjsPKm2Fs?p=preview
<!doctype html>
<html ng-app="plunker" >
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css">
<script>document.write("<base href=\"" + document.location + "\" />");</script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
xx<div admin-select
admin-id="examType"></div>xx
</body>
</html>
and
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
});
app.directive("adminSelect", function () {
return {
restrict: 'A',
require: 'ngModel',
scope: {
adminId: '=adminId'
},
template: '<div id="{{adminId}}"></div>'
};
});
This is not working and I cannot see why. Can someone give me some advice and help me to set the id of the <div> that's part of the template.
You have to put the value of the admin-id attribute under apostrophe because you want to set the value. Example
<div admin-select admin-id="'examType'"></div>
Otherwise you set the scope variable in the controller and pass this variable to the directive:
app.controller('MainCtrl', function($scope) {
$scope.myId = 'examType'
});
<div admin-select admin-id="myId"></div>
Example
template: '<div id="{{$parent.adminId}}"></div>'
Angular's docs has this "the root of the template always gets a new scope.", maybe that's why.
Upddated
this answer is not working... =)

How to filter array if filter is in angular directive?

I try to create general directive for filtering array in angular.
<body ng-controller="MainCtrl">
controller: <input type="text" ng-model="query.name" /> - work<br>
directive: <span filter by="name"></span> - not work
<ul>
<li ng-repeat="item in list | filter:query">{{item.name}}</li>
</ul>
</body>
controller and directive are:
app.controller('MainCtrl', function($scope) {
$scope.list = [
{id: 1, name:'aaa'},
{id: 2, name:'bbb'},
{id: 3, name:'ccc'}
];
});
app.directive('filter', function () {
return {
scope: {
by: '#'
},
link: function postLink(scope, element, attrs) {
element.append(
'<input type="text" ng-model="query.' + attrs.by + '">');
}
}
});
Filter in controller works but filter in directive doesn't. I don't know how to fix it.
Solution is fixed in plunker: http://plnkr.co/edit/WLGd6RPQEwMFRBvWslpt?p=preview
Since you have isolated the scopes you have to use eiter $parent or you have to set up two way binding using '=' i have update your example with two way binding
<!doctype html>
<html ng-app="plunker" >
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
controller: <input type="text" ng-model="query.name" /> - work<br>
directive: <span filter by="query"></span> - not work
<ul>
<li ng-repeat="item in list | filter:query">{{item.name}}</li>
</ul>
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function ($scope) {
$scope.list = [
{ id: 1, name: 'aaa' },
{ id: 2, name: 'bbb' },
{ id: 3, name: 'ccc' }
];
alert("123");
$scope.query = { name: "" }
});
app.directive('filter', function () {
return {
scope: {
by: '='
},
replace: true,
template:'<input ng-model="by.name"></input>'
}
});
</script>
</body>
</html>

Resources