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
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With