I am using selectboxit plugin for the selection list on my angularJS page an have bind the "ng-change" event on it. But unfortunately, it is not giving me the data on change.
index.html
<select data-ng-model="object.word" ng-change="test(object.word)" id="blog-cat">
<option value="" selected="selected">Select...</option>
<option ng-hide="item.name == ''" ng-repeat="item in businessParentItems track by $index" value="{{item.term_id}}" item-business-directive>{{item.name}}</option>
</select>
{{object.word}}
testCtrl.js
$scope.test = function(test) {
console.log('got it!');
}
directive.js
resource_app.directive('itemBusinessDirective', function () {
return function (scope, element, attrs) {
if (scope.$last === true) {
$('.resources-search-bar .container .select-part select').selectBoxIt();
}
};
});
Please help with this to render the ng-model value on change of selection list.
I'm quite new to angular (1), and have hit a problem. I need a custom year picker in my app, that appears in several places. The original code was
html
<select id="yearpicker" ng-model="vm.film.release" required="true" class="form-control">
<option disabled="" selected="" value="">Choose one... </option>
<option disabled="">___________________</option>
<option value="Unknown">Release Year Unknown</option>
<option disabled="">___________________ </option>
</select>
JS
<script>
for (i = new Date().getFullYear(); i > 1900; i--)
{
$('#yearpicker').append($('<option />').val(i).html(i));
};
</script>
Which gave me a nice dropdown with all the years from 1900 to present and a field for years where the year was unknown. But, the code was on the page, which isn't very nice, it meant that I had to load jquery before angular which was kicking out lots of errors, and also it meant that the code was repeated in several places. I pulled the code out, and put it in a directive, so I didn't have to repeat it, and so I could load angular first and get rid of the errors. Which I did like so
Directive JS
angular
.module('myapp')
.directive('customYearpicker', customYearpicker);
function customYearpicker () {
return {
restrict: 'AE',
scope: {
bindModel: '=ngModel'
},
controller: function () {
for (i = new Date().getFullYear(); i >= 1900; i--) {
$('#yearpicker').append($('<option />').val(i).html(i));
};
},
templateUrl: '/common/directives/customYearpicker/customYearpicker.template.html'
};
};
html template
<select id="yearpicker" ng-model="bindModel" class="form-control">
<option value="">Choose one... </option>
<option disabled="">___________________</option>
<option value="Unknown">Release Year Unknown</option>
<option disabled="">___________________ </option>
</select>
and I'm calling it like so
<custom-yearpicker name="release" ng-model="vm.record.release" required="true"></custom-yearpicker>
This works fine everywhere, except where I want to edit the record, and now the select is no longer populated by the value in 'vm.record.release' and is just blank. 'vm.record.release' has the correct value, it is just not displayed in my drop down, but neither is "Choose one... ", as with all other instances. Apart from this the yearpicker works fine, but this needs fixing.
If anyone can point out the (most likely) glaringly obvious blunder I've made, or point me in the right direction if I'm doing it all wrong, it would be much appreciated.
Thanks.
UPDATE
So after being advised to use ng-options, I have now updated my directive to this:
angular
.module('myapp')
.directive('customYearpicker', customYearpicker);
function customYearpicker () {
return {
restrict: 'AE',
scope: {
bindModel: '=ngModel'
},
controller: function ($scope) {
$scope.selectOptions = [
{ name: '', text: 'Choose one... ' },
{ name: '', text: '___________________' },
{ name: 'Unknown', text: 'Release Year Unknown' },
{ name: '', text: '___________________' },
];
for (i = new Date().getFullYear(); i >= 1900; i--) {
// $('#yearpicker').append($('<option />').val(i).html(i));
var newOpt = { name: i, text: i};
$scope.selectOptions.push(newOpt);
};
console.log($scope.selectOptions);
return $scope.selectOptions;
},
templateUrl: "/common/directives/customYearpicker/customYearpicker.template.html"
};
};
and the html template to this:
<select id="yearpicker" ng-model="bindModel" ng-options="option.name as option.text for option in selectOptions" class="form-control"> </select>
and I am calling it like this:
<custom-yearpicker name="release" ng-model="vm.record.release" required="true"></custom-yearpicker>
The problem is that even though it works much as before, my disabled options are no longer disabled, and the yearpicker is still not showing the value of vm.record.release. If I pick a value from the selector it is picked up by the edit controller with no problems, it just isn't selected in the selector for some reason. Still looking for suggestions please.
When bootstrapping your app, you need to declare the dependencies. If there are none, just use an empty array.
var app = angular.module('myapp', []);
app.directive('customYearpicker', customYearpicker);
function customYearpicker () {
return {
restrict: 'AE',
scope: {
bindModel: '=ngModel'
},
controller: function () {
for (i = new Date().getFullYear(); i >= 1900; i--) {
$('#yearpicker').append($('<option />').val(i).html(i));
};
},
template: `<select id="yearpicker" ng-model="bindModel" class="form-control"><option value="">Choose one... </option><option disabled="">___________________</option><option value="Unknown">Release Year Unknown</option><option disabled="">___________________ </option></select>`
};
};
Notice I used template instead of templateUrl for expediency on my end, but your templateUrl should work.
Also, I should mention that this is not the Angular way of creating selects. Please look into ngOptions.
You shouldn't use jQuery for such things.
directive code:
function customYearSelect(){
return {
restrict: 'E',
scope: {
model: '=ngModel',
name: '#',
yearFrom: '#',
yearTo: '#'
},
templateUrl: 'custom-year-select.template.html',
link: function (scope,element,attr) {
var yearFrom = attr['yearFrom'] ? attr['yearFrom'] : 1990;
var yearTo = attr['yearTo'] ? attr['yearTo'] : new Date().getFullYear();
scope.yearArray = [];
for(var i = yearTo; i >= yearFrom; i--){
scope.yearArray.push(i);
}
}
}
}
template:
<select name="custom-year-selet" ng-model="model" ng-options="name + ' ' + year for year in yearArray">
<option name="selectYear" value="" style="display:none">-- select year --</option>
</select>
HTML:
<custom-year-select name="Release year:" ng-model="selectedYear2"
year-from="2000" year-to="2005"></custom-year-select>
Here's a working jsfiddle: http://jsfiddle.net/kvda7Lc7/
Ok, I figured it out. In the end it was just me being a bit dopey, the fix was:
for (i = new Date().getFullYear(); i >= 1900; i--) {
// $('#yearpicker').append($('<option />').val(i).html(i));
var newOpt = { name: String(i), text: String(i) };
$scope.selectOptions.push(newOpt);
};
I just needed to parse the dates, doh!
Well thanks for the help anyway, I now have a directive doing it the angular way, instead of some bodgy jquery hack, and it all works .
Thanks for setting me on the right track Jorge.
I am trying to perform a case-insensitive bind of an ng-model to a dynamic select drop-down using AngularJS.
by going through various other relavent answers from stack over flow, i have come up with something like below on the view , here caseinsensitive-options is an directive which i have come up with referencing the following solution
AngularJS case-insensitive binding to a static select drop-down
HTML:
<select id="dcName" caseinsensitive-options="" ng-model="DC.name" class="form-control">
<option value="">--- Please Select ---</option>
<option ng-repeat="dataCenter in inventoryDataCenters" value="{{dataCenter}}">{{dataCenter}}</option>
</select>
js directive code :
app.directive('caseinsensitiveOptions', function() {
return {
restrict: 'A',
require: ['ngModel', 'select'],
link: function(scope, el, attrs, ctrls) {
var ngModel = ctrls[0];
ngModel.$formatters.push(function(value) {
var option = [].filter.call(el.children(), function(option) {
return option.value.toUpperCase() === value.toUpperCase()
})[0];
return option ? option.value : value
});
}
}
});
The expected result is
when i pass something like this for
$scope.inventoryDataCenters = ["TEST1","test2",teST3]; and ng-model for DC.name has value TesT1.
The drop down should show TEST1 by doing case insensitive binding. That doesnt happen now. The above solution works perfect when we have static drop down.
things to be considered is that the select is inside a div which ng-repeat as shown below
ng-repeat="DC in workflowData.project_data.service_info.variables.service_data['data-center']"
and ng-model for select DC.name is derived from the above array DC.
check this URL for binding based on case insensitive value
https://jsfiddle.net/dwd2du17/6/
<div ng-app="module" ng-controller="controller as ctrl">
<select id="animal" ng-model="ctrl.animal">
<option value="">--- Select ---</option>
<option value="CaT">Cat</option>
<option value="DOg">Dog</option>
</select>
{{ctrl.animal}}
</div>
var appForm = angular.module('module', [])
.controller('controller', function($scope) {
});
I am exploring advanced features in AngularJS such as custom directives. I want to have a textbox which by using custom directive should allow either numbers only or text only depending upon the value chosen by the user from a dropdown box. I have managed to create a custom directive which allows numbers only based upon AngularJs Custom Directive fails the text box validation . I am not sure how to apply a custom directive dynamically to the same textbox. I have create another custom directive which allows text only, but not sure how to replace the number only directive with the text only directive dynamically.
<body>
<div ng-app="TextboxExample" ng-controller="ExampleController">
<form name="shippingForm" novalidate>
<select id="textBoxOptions" >
<option value="number" selected="selected">Numbers Only</option>
<option value="text">Text Only</option>
<option value="special">Special Characters</option>
<option value="any">Any Value</option>
</select>
<input id="customTextBox" unbindable number-only-input type="text" name="name" ng-model="testvalue.number" required />
<span class="error" ng-show="shippingForm.name.$error.required">
Please enter a value
</span>
</form>
</div>
<script src="scripts/angular.js"></script>
<script src="scripts/jquery.min.js"></script>
<script>
$("select").change(function () {
var selected = $("#textBoxOptions").val();
$('#customTextBox').attr("ng-model", selected);
});
</script>
<script>
angular.module('TextboxExample', [])
.controller('ExampleController', ['$scope', function ($scope) {
$scope.testvalue = { number: 1, validity: true };
}])
.directive('numberOnlyInput', ['$compile', function ($compile) {
return {
link: function (scope, element, attrs) {
var watchMe = attrs["ngModel"];
scope.$watch(watchMe, function (newValue, oldValue) {
if (newValue == undefined || newValue == null || newValue == "") {
return;
} else if (isNaN(newValue)) {
var myVal = watchMe.split(".");
switch (myVal.length) {
case 1:
scope[myVal[0]] = oldValue;
break;
case 2:
scope[myVal[0]][myVal[1]] = oldValue;
}
}
$compile(element)(scope);
});
}
};
}]);
</script>
When I change the value in the dropdown box, it correctly changes the ng-model on customTextBox as checked by inspect element. However, I am not sure how to create and apply multiple directives. Thanks
There are several possibilities. You can switch directive atttibute or whole elements:
<input {{ yourmode ? number-directive : text-directive }} ng-model="data">
or
<input ng-show="yourmode" number-directive ng-model="data">
<input ng-show="!yourmode" text-directive ng-model="data">
or you change the mode with dynamic directive attributes
<input directive-data="yourmode" my-input-directive ng-model="data">
I create customdirective and want to ng-model update before ng-change fire. Currently ng-change fire before udpate ng-mdoel value below is my code.
Main issue is coming when i change page number in dropdown list. It alert with previous value. I think ng-mdoel update after ng-change fire. but i want ng-model fire before ng-change.
app.directive('bottomPagination', function () {
var directive = {
templateUrl: '/App/Common/directives/bottomPagination.html',
restrict: 'A',
replace: true,
scope: {
currentPage: '=',
changePageSize: '&'
}
};
return directive;
});
//here is html directive (/App/Common/directives/bottomPagination.html)
<select id="pagesizeddl" ng-model="pageSize" ng-change="changePageSize()">
<option>5</option>
<option>10</option>
<option>20</option>
<option>30</option>
</select>
// here is my html page where i used directive
<div data-ng-controller="ProductsList as vm">
<div data-bottom-pagination
data-page-size="vm.paging.pageSize"
data-change-page-size="vm.changePageSize()"
>
</div>
</div>
// This is contrller
(function () {
// Start Products List function
var ListControllerId = 'ProductsList';
angular.module('app').controller(ListControllerId,
['$scope', ListController]);
function ListController($scope) {
var vm = this;
vm.paging = {
pageSize: 10
};
vm.changePageSize = changePageSize;
function changePageSize() {
alert(vm.paging.pageSize);
}
}
})();
Hi I recently had the same problem.
My best practice solution is to add a parameter in the ng-change function in your directive template. You need to add the parameter as an JSON Object!
<select id="pagesizeddl" ng-model="pageSize" ng-change="changePageSize({pageSize:pageSize})">
<option>5</option>
<option>10</option>
<option>20</option>
<option>30</option>
</select>
The property "pageSize" (of the JSON Object) will be matched with the parameter of your directive function vm.changePageSize(pageSize). So it is necessary that both have the same name!
<div data-ng-controller="ProductsList as vm">
<div data-bottom-pagination
data-page-size="vm.paging.pageSize"
data-change-page-size="vm.changePageSize(pageSize)"
>
</div>
Now you only have to alter your controller function like this:
function changePageSize(pageSize) {
alert(pageSize);
}