So, I have the same question asked on this question, sadly, no one has answered, so, here it goes again
I'm trying to create a select directive, where I can send the ng-options as a parameter.
This is my directive
app.directive('dropDown', function () {
return {
restrict: 'E',
template: function (element, attrs) {
return '<div class="col-sm-{{labelCol}} control-label">' +
'<label>{{label}}:</label>' +
'<div>' +
'<div clas="col-sm-{{controlCol}}">' +
'<label style="cursor:pointer" ng-show="!edit && forEdit" ng-disabled="disabled" ng-click="edit = true;">{{ngModel}}</label>' +
'<i ng-show="!edit && forEdit && !disabled" class="fa fa-pencil-square-o" style="cursor:pointer" aria-hidden="true" ng-click="edit = true;"></i>' +
'<select name="{{name}}" ng-change="ngChange" ng-blur="edit = false" ng-show="edit || !forEdit" class="form-control" ng-model="ngModel" ng-required="required" ng-options={{options}}/>' +
'</div>'
},
replace: true,
scope: {
ngModel: '=',
ngChange: '&',
label: '#',
labelCol: '#',
controlCol: '#',
type: '#',
name: '#',
disabled: '=',
required: '=',
forEdit: "=",
options: "#"
},
link: function (scope, element, attrs) { },
compile: function (element, attrs) {
if (!attrs.labelCol) attrs.labelCol = '4';
if (!attrs.controlCol) attrs.controlCol = '8';
if (!attrs.required) attrs.required = false;
if (!attrs.disabled) attrs.disabled = false;
if (!attrs.forEdit) attrs.forEdit = false;
attrs.edit = !attrs.forEdit;
}
}
})
And this is a implementation of the directive
<div class="row">
<drop-down ng-model="site" for-edit="true" label="Site Test" options="x.SITE_CODE as x.SITE_NAME for x in sites"></drop-down>
</div>
<div class="row">
<drop-down ng-model="site1" for-edit="true" label="Site Test" options="x for x in sites1"></drop-down>
</div>
And I'm getting the same response
Error: [$parse:syntax] Syntax Error: Token 'in' is an unexpected token
at column 3 of the expression [x in sites1] starting at [in sites1].
Error: [$parse:syntax] Syntax Error: Token 'as' is an unexpected token
at column 13 of the expression [x.SITE_CODE as x.SITE_NAME for x in
sites] starting at [as x.SITE_NAME for x in sites].
Any idea how to achieve my desired result?
Edit1:
If it help, here's the arrays that should be filling the selects
$scope.sites = JSON.parse("[{\"SITE_CODE\":\"1\",\"SITE_NAME\":\"SITE1\",},{\"SITE_CODE\":\"2\",\"SITE_NAME\":\"SITE2\"},{\"SITE_CODE\":\"3\",\"SITE_NAME\":\"SITE3\"},{\"SITE_CODE\":\"4\",\"SITE_NAME\":\"SITE4\"}]");
$scope.sites1 = ["SITE1", "SITE2", "SITE3", "SITE4"];
Edit 2:
Added the error for the more complex ng-options sentence
Edit 3:
So, I just realized that, I'm setting the ngOptions as a 2 way databinding field on the scope, as, it's not necesary, so I changed it from = to # and now, I'm getting another error message
Error: [$compile:ctreq] Controller 'select', required by directive 'ngOptions', can't be found!
Which, it's unreasonable, as I'm indeed setting the ngOptions, and I can verify it on the compile
Edit 4:
So, after some testing, I'm finally getting my controls rendered, but sadly, withouth values
The selects are clearly on the controller div
<div class="content" ng-controller="testController">
<div class="row">
<drop-down ng-model="site" for-edit="true" label="Site Test" options="x for x in sites"></drop-down>
</div>
<div class="row">
<drop-down ng-model="site" label="Site Test" options="x for x in sites"></drop-down>
</div>
<div class="row">
<drop-down ng-model="site1" for-edit="true" label="Site Test" options="x for x in sites1"></drop-down>
</div>
</div>
The controller indeed has this collections
app.controller('testController', ['$scope', function ($scope) {
$scope.sites = JSON.parse("[{\"SITE_CODE\":\"1\",\"SITE_NAME\":\"SITE1\",},{\"SITE_CODE\":\"2\",\"SITE_NAME\":\"SITE2\"},{\"SITE_CODE\":\"3\",\"SITE_NAME\":\"SITE3\"},{\"SITE_CODE\":\"4\",\"SITE_NAME\":\"SITE4\"}]");
$scope.sites1 = ["SITE1", "SITE2", "SITE3", "SITE4"];
}]);
But my rendered controls comes without any values
This is the rendered html for one of the controls
<div ng-model="site" label="Site Test" options="x for x in sites" class="ng-isolate-scope ng-valid">
<div class="col-sm-4 control-label"><label class="ng-binding">Site Test:</label></div>
<div class="col-sm-8">
<label style="cursor:pointer" ng-show="!edit && forEdit" ng-disabled="disabled" ng-click="edit = true;" class="ng-binding ng-hide"></label>
<i ng-show="!edit && forEdit && !disabled" class="fa fa-pencil-square-o ng-hide" style="cursor:pointer" aria-hidden="true" ng-click="edit = true;"></i>
<select name="" ng-change="ngChange" ng-blur="edit = false" ng-show="edit || !forEdit" class="form-control ng-pristine ng-valid ng-valid-required ng-touched" ng-model="ngModel" ng-required="required" ng-options="x for x in sites">
<option value="?" selected="selected"></option>
</select>
</div>
</div>
At least now I'm getting my controls rendered, now, on to show some values on them
The syntax ng-options="x in sites1" is incorrect.
In it's most simplest form it should be label for value in array:
ng-options="x for x in sites1"
Also check out the angular docs for ngOptions to see all of the permitted argument forms.
Well, after much testing, I finally am able to achieve my desired result.
I'll leave the directive here to whoever might want to use it, as it allows to
Set a desired options string
Set a property to show in case we store the complete object in the model
Disabled status, that will only show the model value
Inline edit of the value
var app = angular.module("app", []);
app.controller('testController', ['$scope', function($scope) {
$scope.sites = JSON.parse("[{\"SITE_CODE\":\"1\",\"SITE_NAME\":\"TEST 1\"},{\"SITE_CODE\":\"2\",\"SITE_NAME\":\"TEST 2\"},{\"SITE_CODE\":\"3\",\"SITE_NAME\":\"TEST 3\"},{\"SITE_CODE\":\"4\",\"SITE_NAME\":\"TEST 4\"}]");
$scope.sites1 = ["TEST 1", "TEST 2", "TEST 3"];
}]);
app.directive('dropDown', function() {
return {
restrict: 'E',
require: 'ngOptions',
template: function(element, attrs) {
return '<div>' +
'<div class="col-sm-{{labelCol}} control-label">' +
'<label>{{label}}:</label>' +
'</div>' +
'<div class="col-sm-{{controlCol}}">' +
'<label ng-show="!edit && forEdit">{{ngModel[textValue] !== undefined ? ngModel[textValue] : ngModel}}</label> ' +
'<span ng-show="!edit && forEdit && !disabled" class="fa fa-pencil-square-o" style="cursor:pointer" aria-hidden="true" ng-click="edit = true;">click here for edit</span>' +
'<select name="{{name}}" ng-change="ngChange" ng-blur="edit = false" ng-show="edit || !forEdit" class="form-control" ng-model="ngModel" ng-required="required" ng-options="{{options}}"/>' +
'</div>' +
'</div>';
},
replace: true,
scope: {
ngModel: '=',
ngChange: '&',
label: '#',
labelCol: '#',
controlCol: '#',
type: '#',
name: '#',
disabled: '=',
required: '=',
forEdit: "=",
options: "#",
items: "=",
textValue: "#"
},
compile: function(element, attrs) {
if (!attrs.labelCol) attrs.labelCol = '4';
if (!attrs.controlCol) attrs.controlCol = '8';
if (!attrs.required) attrs.required = false;
if (!attrs.disabled) attrs.disabled = false;
if (!attrs.forEdit) attrs.forEdit = false;
if (attrs.disabled)
attrs.forEdit = "true";
attrs.edit = !attrs.forEdit;
},
link: function(scope, element, attrs) {
},
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div class="" ng-controller="testController">
<div class="row">
<drop-down ng-model="site" for-edit="true" label="Site Test Inline" text-value="SITE_NAME" options="x.SITE_NAME for x in items" items="sites"></drop-down>
<drop-down ng-model="site1" for-edit="false" label="Site Test Select" options="x for x in items" items="sites1"></drop-down>
<drop-down ng-model="site1" disabled="true" label="Site Test Disabled" options="x for x in items" items="sites1"></drop-down>
</div>
</div>
</div>
I am having a problem with my code basically i have this span (dynamically created via ng-repeat)
<span my-size id="abc"></span>
<span my-size id="def"></span>
<span my-size id="ghi"></span>
what I need to achieve is to get the id of each span and split its character and created checkbox and used the split[] i get when i split the id to be its value
<span id="abc">
<input type="checkbox" value="a">
<input type="checkbox" value="b">
<input type="checkbox" value="c">
</span>
<span id="def">
<input type="checkbox" value="d">
<input type="checkbox" value="e">
<input type="checkbox" value="f">
</span>
<span id="ghi">
<input type="checkbox" value="g">
<input type="checkbox" value="h">
<input type="checkbox" value="i">
</span>
could anyone help me do this in angular js directives
this is all i have so far :
myApp.directive('mySize', function () {
return {
restrict: 'E',
scope: { html: '#' },
template: '<span ng-bind-html="html"></span>',
link : function (scope, element, attrs) {
scope.html="<h1>sample html </h1>";
}
}
});
I can't go further since my directives wont generate html tags
I'm not sure what your initial intention was when writing the directive, because there is really no need to either use a link-function or ng-bind-html.
For what you've asked the directive could be as simple as:
(function (app, ng) {
'use strict';
app.directive('mySize', function () {
return {
restrict: 'A',
scope: { id: '#id' },
template: '<input type="checkbox" data-ng-repeat="char in id track by $index" value="{{ char }}">'
}
});
}(angular.module('app', []), angular));
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.1/angular.min.js"></script>
<div data-ng-app="app">
<span data-my-size id="abc"></span>
<span data-my-size id="def"></span>
<span data-my-size id="ghi"></span>
</div>
Edit
If you you want to add extra information just fiddle with the template. E.g.:
(function (app, ng) {
'use strict';
app.directive('mySize', function () {
return {
// actually obsolute, because it's the default setting
restrict: 'A',
// reusing the directive name to simplify the required view-html,
// but mapping it to a more fitting name when used internally
scope: { str: '#mySize' },
// the actual template (this time using a label)
template: '<label data-ng-repeat="char in str track by $index"><input type="checkbox" value="{{ char }}"> {{ char }}</label>'
}
});
}(angular.module('app', []), angular));
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.1/angular.min.js"></script>
<div data-ng-app="app">
<div data-my-size="abc"></div>
<div data-my-size="def"></div>
<div data-my-size="ghi"></div>
</div>
It doesn't work because you restricted it's usage to element and use it as attribute. Change restrict: 'E' to restrict: 'A'.
var app = angular.module('app', []);
app.directive('mySize', function($sce) {
return {
restrict: 'EA',
scope: {
id: '#'
},
template: '<label ng-repeat="i in array"><input type="checkbox" ng-value="i" >{{i}}<label>',
link: function(scope, element, attrs) {
scope.array = scope.id.split("")
}
}
});
app.controller('homeCtrl', function($scope) {
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="homeCtrl">
<span my-size id="abc"></span>
<span my-size id="def"></span>
<span my-size id="ghi"></span>
</div>
</div>
The directive can look like this:
.directive('mySize', function() {
return {
restrict: 'AE',
link: function(scope, element, attrs) {
element[0].id.split('').map(function(el) {
element.append('<label><input type="checkbox" value="' + el + '"> ' + el + '</label>');
});
}
}
});
Demo: http://plnkr.co/edit/nZMEdUjMXG3MDYv19H5C?p=preview
code for the directive template
//"textBox.html"
<div class="well">
<label class="control-label">Text</label>
<div class="controls">
<input id="label" type="text" class="txt span3" ng-model="label" placeholder='Label for text field...'>
<input type="text" class="span3" ng-model="value" placeholder='Default value...'>
<input type="text" class="span3" ng-model="helpText" placeholder="Help text...">
<input type="checkbox" class="span1" ng-model="required" ng-true-value="true" ng-false-value="false">Required
<input type="checkbox" class="span1" ng-model="advanced" ng-true-value="true" ng-false-value="false">Advanced?
<img src="../../images/bullet_cross.png" alt="Remove" style="cursor: pointer" id="text" border="0" ng-click="deleteField($event)">
</div>
</div>
directive is using like this in main html page
//"algorithm.html"
<text-box></text-box>
controller for the custom directive
//"controller.js"
var algorithm = angular.module('algorithmController',[]);
/***********directive to render text field***********/
algorithm.directive('textField' , function(){
return{
restrict: 'E',
templateUrl: '../partials/algorithm/textBox.html',
require: 'ngModel',
replace: true,
link: function(scope, iElement, iAttrs, ngModelCtrl) {
// how should i get updated data(i.e. if user change after typing) over here entered by user??
}
};
});
You can create an isolate scope using the '=' syntax, which will create two way binding to your controller and the directive. You don't even necessarily need ngModel required in your directive.
.directive("textField", function () {
return {
restrict : "E",
template : "<input type='text' ng-model='val'/>",
scope : {
val : "="
}
};
});
Here is a very simple example doing what you requested;
http://jsfiddle.net/smaye81/xaohrv53/2/
i am using datepicker but here facing problem regarding model value not binding to model when i select date its nothing happen, any one can tell me where i am doing wrong must be appreciated. here i am sending my code.Showing date picker just problem after selecting date value not not binding to ng-model="user.dob".
signUpview.html
<div class="col-md-6">
<label for="datepicker" class="col-lg-5 form-label">Date Of Birth:</label>
<div class="col-lg-7">
<input type="text" class="form-control dateBirth" ng-model="user.dob" id="datepicker" name="datepicker" datepicker placeholder="Date Of Birth" required/>
<div class="error" ng-show="newUser_form.datepicker.$dirty && newUser_form.datepicker.$invalid">
<small class="error errorFields" ng-show="newUser_form.datepicker.$error.required"> Date is required.</small>
</div>
</div>
</div>
datepickerDirective.js
app.directive('datepicker', function() {
var linker = function(scope, element, attrs) {
element.datepicker().on('changeDate', function(){
console.log(scope);
$(".datepicker").hide();
});
}
return {
require: 'ngModel',
restrict: 'A',
link: linker
}
});
you can use ngModel.$setViewValue update the model property
app.directive('datepicker', function() {
var linker = function(scope, element, attrs,ngModelCtrl) {
element.datepicker().on('changeDate', function(){
console.log(scope);
ngModelCtrl.$setViewValue(value);//value is datepicker selected date;
$(".datepicker").hide();
});
}
return {
require: 'ngModel',
restrict: 'A',
link: linker
}
});
I created a directive with select template but i need the "name" tag so i can put a validation and i don't know how to add that. I tried adding attr but it didn't work.
Here is the fiddle
<form name="newForm" ng-submit="save()">
<div>
Name: <input required ng-model="newSupplier.Name" name="myName" type="text" required/>
<span ng-show="newForm.myName.$error.required">*</span>
<br />
Status: <keywords name="myStatus" title="Choose Status" label="" array="myKeyword" keyword-type="ActivityType" supplier-id="newSupplier.Id" opt-value="Id" opt-description="Description"></keywords>
<span ng-show="newForm.myStatus.$error.required">*</span>
<br>
<button type="submit">Save</button>
<br /><i>How to save the ID of the selected dropdown?</i>
</div>
</form>
JS
app.directive('keywords', function(){
return {
restrict: 'E',
scope: {
array: '=',
supplierId : '='
},
template: '<label>{{label}}</label>' +
'<select ng-model="supplierId" ng-options="a[optValue] as a[optDescription] for a in array | filter: keywordType">' +
'<option style="display: none" value="">-- {{title}} --</option>' +
'</select>',
link: function (scope, element, attrs) {
scope.label = attrs.label;
scope.title = attrs.title;
scope.optValue = attrs.optValue;
scope.optDescription = attrs.optDescription;
scope.keywordType = attrs.keywordType;
}
};
});
You need to add "required" to your "keywords" directive to make validation works.
template: '<label>{{label}}</label>' +
'<select ng-model="supplierId" ng-options="a[optValue] as a[optDescription] for a in array | filter: keywordType" required>' +
'<option style="display: none" value="">-- {{title}} --</option>' +
'</select>',
This is the updated demo
Hope this is helpful for you.