Whenever the user picks 10 in the dropdown (either formData.minRating or formData.maxRating)in main.html it evaluates to 1. I found this out by testing how the ng-change in main.html evaluates. If I pick the formData.maxRating to be 10 and then formData.minRating to be 2, it will say that the minRating is larger than the maxRating which isn't true. But when I do console.log's for all of the variables, it says they're the correct values. So I don't know what's wrong. How do I get the 10 to evaluate to 10 and not 1?
main.html
<div layout="column" layout-align="center">
<div>
<md-input-container>
<md-label>Set Genre</md-label>
<md-select ng-model="formData.selectedGenre" ng-change="setGenreId(formData.selectedGenre)" placeholder="Genre">
<md-option ng-repeat="genre in genreList" value="{{genre.id}}">{{genre.name}}</md-option>
</md-select>
</md-input-container>
</div>
<div>
<md-input-container>
<md-label>Set Min Rating</md-label>
<p style="color:red" ng-show="formData.minRating > formData.maxRating"> Min rating cannot be larger than max rating</p>
<md-select ng-model="formData.minRating" ng-change="setMinRating(formData.minRating)">
<md-option ng-repeat="num in [1,2,3,4,5,6,7,8,9,10]" value="{{num}}">{{num}}</md-option>
</md-select>
</md-input-container>
</div>
<div>
<md-input-container>
<md-label>Set Max Rating</md-label>
<md-select ng-model="formData.maxRating" ng-change="setMaxRating(formData.maxRating)">
<md-option ng-repeat="num in [1,2,3,4,5,6,7,8,9,10]" value="{{num}}">{{num}}</md-option>
</md-select>
</md-input-container>
</div>
<div>
<md-button class="md-raised md-primary" ng-disabled="formData.minRating >= formData.maxRating">Submit</md-button>
</div>
</div>
main.js
angular.module('pickMeAmovieApp')
.controller('MainCtrl',function ($scope,movieFactory,sharedProperties) {
$scope.genreList = [];
getGenres();
$scope.values = [1,2,3,4,5,6,7,8,9,11];
$scope.formData = {};
$scope.formData.minRating = sharedProperties.getMinRating();
$scope.formData.maxRating = sharedProperties.getMaxRating();
function getGenres(){
movieFactory.getGenres().then(function(response){
$scope.genres = response['genres'];
angular.forEach($scope.genres, function(value) {
$scope.genreList.push(value);
});
});
};
$scope.setGenreId = function (genreId){
sharedProperties.setGenreId(genreId);
console.log(sharedProperties.getGenreId());
};
$scope.setMaxRating = function (rating){
sharedProperties.setMaxRating(rating);
//$scope.maxRating = sharedProperties.getMaxRating();
console.log("max: " + $scope.formData.maxRating);
console.log("min: " + $scope.formData.minRating);
};
$scope.setMinRating = function (rating){
sharedProperties.setMinRating(rating);
//$scope.minRating = sharedProperties.getMinRating();
console.log("min: " + $scope.formData.minRating);
console.log("max: " + $scope.formData.maxRating);
};
});
sharedProperties.js
angular.module('pickMeAmovieApp')
.service('sharedProperties', function () {
// AngularJS will instantiate a singleton by calling "new" on this function
var _genreId = null;
var _minRating = 1;
var _maxRating = 10;
this.getGenreId = function () {
return _genreId;
};
this.setGenreId = function(value) {
_genreId = value;
};
this.getMinRating = function() {
return _minRating;
};
this.setMinRating = function(rating){
_minRating = rating;
};
this.getMaxRating = function(){
return _maxRating;
};
this.setMaxRating = function(rating){
_maxRating = rating;
};
});
Angular is treating each of the values as strings
you can check by using typeof formData.maxRating
In your JS, write:
$scope.parseInt = function(i) {
return parseInt(i);
};
In your HTML, use:
<div>
<md-button class="md-raised md-primary" ng-disabled="parseInt(formData.minRating) >= parseInt(formData.maxRating)">Submit</md-button>
</div>
Related
I'm trying to use angular rating from this http://plnkr.co/edit/kFKejRU0G2wmkD7GlNdH?p=preview
Here is my Angular code:
var ProfileApp = angular.module('ProfileApp', ['ui.bootstrap']);
ProfileApp.controller('getprofile', function($scope, $http) {
//Some codes are here
})
var RatingDemoCtrl = function ($scope) {
$scope.myRate = 0;
$scope.submit = function() {
console.log($scope.percent) ; //null
}
$scope.rate = 1;
$scope.max = 5;
$scope.isReadonly = false;
$scope.percent = 20;
$scope.hoveringOver = function(value,object) {
console.log('hoveringOver', value);
$scope.overStar = value;
$scope.percent = (100 * $scope.overStar) / $scope.max;
};
$scope.hoveringLeave = function(rate) {
console.log('hoveringLeave', $scope.rate);
$scope.percent = (100 * $scope.rate) / $scope.max;
};
};
Above code is used for Rating.
Here is the html code.
<body id="home" ng-app="ProfileApp">
<div ng-controller="getprofile">
//Some html codes
<div ng-controller="RatingDemoCtrl" class="well well-small">
<form class="Scroller-Container" ng-submit="submit()" ></form>
<rating value="rate" max="max" readonly="isReadonly" on-hover="hoveringOver(value)" on-leave="hoveringLeave(rate)" ></rating>
<span class="badge" ng-class="{'badge-warning': percent<30, 'badge-info': percent>=30 && percent<70, 'badge-success': percent>=70}" ng-show="overStar && !isReadonly">{{percent}}%</span>
<input type="submit" id="submit" value="Submit" />
</form>
<pre>{{percent}}</pre>
</div>
As you can see I have nested controller and this is giving me error Error: [ng:areq].
What can be done now? Is there any way I can fix it?
Update
After using the code of saj now I am getting error.
angular.min.js:101 Error: [ngRepeat:dupes] http://errors.angularjs.org/1.3.2/ngRepeat/dupes?p0=r%20in%20range&p1=object%3A10&p2=%7B%22stateOn%22%3Anull%2C%22stateOff%22%3Anull%7D
No star is vising. I inspect the code and codes are below.
<div ng-controller="RatingDemoCtrl" class="well well-small ng-scope">
<form class="Scroller-Container ng-pristine ng-valid" ng-submit="submits()"></form>
<span ng-mouseleave="reset()" value="rate" max="max" readonly="readonly" on-hover="hoveringOver(value)" on-leave="hoveringLeave(rate)" class="ng-isolate-scope">
<!-- ngRepeat: r in range -->
</span>
<span class="badge ng-binding badge-warning ng-hide" ng-class="{'badge-warning': percent<30, 'badge-info': percent>=30 && percent<70, 'badge-success': percent>=70}" ng-show="overStar && !isReadonly">20%</span>
<input type="submit" id="submit" value="Submit">
<pre class="ng-binding">20</pre>
</div>
You just need to separate out 'RatingDemoCtrl' controller
app.controller('RatingDemoCtrl', function($scope) {
$scope.myRate = 0;
$scope.submit = function() {
console.log($scope.percent); //null
}
$scope.rate = 1;
$scope.max = 5;
$scope.isReadonly = false;
$scope.percent = 20;
$scope.hoveringOver = function(value, object) {
console.log('hoveringOver', value);
$scope.overStar = value;
$scope.percent = (100 * $scope.overStar) / $scope.max;
};
$scope.hoveringLeave = function(rate) {
console.log('hoveringLeave', $scope.rate);
$scope.percent = (100 * $scope.rate) / $scope.max;
};
});
WORKING DEMO
I'm working with the AngularJS material design library, and I'm looking to make a input box, with a floating label, with autocomplete, and chips to denote the options the users have selected. The best I've gotten is:
https://codepen.io/anon/pen/eeqBKK
HTML:
<div ng-controller="CustomInputDemoCtrl as ctrl" layout="column" ng-cloak="" class="chipsdemoCustomInputs" ng-app="MyApp">
<md-content class="md-padding" layout="column">
<md-chips ng-model="ctrl.selectedVegetables" md-autocomplete-snap="" md-transform-chip="ctrl.transformChip($chip)" md-require-match="ctrl.autocompleteDemoRequireMatch">
<md-autocomplete md-selected-item="ctrl.selectedItem" md-search-text="ctrl.searchText" md-items="item in ctrl.querySearch(ctrl.searchText)" md-item-text="item.name" placeholder="Choose your favourite colors">
<span md-highlight-text="ctrl.searchText">{{item.name}}</span>
</md-autocomplete>
<md-chip-template>
<span>
<strong>{{$chip.name}}</strong>
<em>({{$chip.type}})</em>
</span>
</md-chip-template>
</md-chips>
</md-content>
</div>
JavaScript:
(function () {
'use strict';
angular
.module('MyApp',['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.controller('CustomInputDemoCtrl', DemoCtrl);
function DemoCtrl ($timeout, $q) {
var self = this;
self.readonly = false;
self.selectedItem = null;
self.searchText = null;
self.querySearch = querySearch;
self.colors = loadColors();
self.selectedColors = [];
self.numberChips = [];
self.numberChips2 = [];
self.numberBuffer = '';
self.autocompleteDemoRequireMatch = true;
self.transformChip = transformChip;
function transformChip(chip) {
if (angular.isObject(chip)) {
return chip;
}
return { name: chip, type: 'new' }
}
function querySearch (query) {
var results = query ? self.colors.filter(createFilterFor(query)) : [];
return results;
}
function createFilterFor(query) {
var lowercaseQuery = angular.lowercase(query);
return function filterFn(colors) {
return (colors._lowername.indexOf(lowercaseQuery) === 0) ||
(colors._lowertype.indexOf(lowercaseQuery) === 0);
};
}
function loadColors() {
var colorOptions = [{'name': 'Red','type': 'Color'},{'name': 'Orange','type': 'Color'},{'name': 'Yellow','type': 'Color'},{'name': 'Green','type': 'Color'},{'name': 'Blue','type': 'Color'},{'name': 'Purple','type': 'Color'}
];
return colorOptions.map(function(col) {
col._lowername = col.name.toLowerCase();
col._lowertype = col.type.toLowerCase();
return col;
});
}
}
})();
Which, has the input box, the autocomplete, the chips to denote the options but not the floating label on the text area. Is it possible to have the floating label in this setup?
I just want to scroll downside and after that come back to the beginning of the list.
Now I can't use my grid.
I know that there are thousands of examples of how to do ui-scroll,
but there are no any example with Angular 1.5 components
Please help.
index.html
//add ui-scroll-viewport
<md-content flex layout-padding class="viewport" id="viewport-serviceDatasource" ui-scroll-viewport>
// added ui-scroll, this part is responsible for loading by week
<div layout="raw" layout-xs="column" class="week" layout-sm="column" layout-align="space-between start" flex="none"
ui-scroll="week in $ctrl.grid">
<!-- outlines days -->
<div flex="none" layout="column" layout-fill ng-repeat="day in week">
<!-- current day header-->
<div layout="row" layout-align="space-between center" flex-gt-sm="none" flex="none" style="height: 30px">
<div flex="none" class="md-body-1" style="min-width: 24px">{{::day.title}}</div>
</div>
</div>
</div>
</md-content>
app.js
class CalendarCtrl {
constructor($log, $q, $timeout, $scope) {
'ngInject';
this._$log = $log;
this._$q = $q;
this._$timeout = $timeout;
this._$scope = $scope;
this.grid = {};
// Tried to use $Scope
this._$scope.grid = {};
}
$onInit() {
// Get the first day of the week curry
let currDay = moment().weekday(0),
startDay = moment(currDay).add(-5,'w'),
endDay = moment(currDay).add(5,'w');
// Error here. I think so
this.getCalendarGrid(startDay, endDay).then(
(success) => {
// Get all our days, in the form of a grid
var result = success;
var grid = {};
grid.get = (index, count, success) =>{
index = index <= 0 ? index + 1 : index -1;
success(result.slice(index, index + count));
};
this.grid = grid;
this._$log.debug('Calendar: getCalendarGrid', this.grid);
},
(error) => this._$log.debug('Calendar: onInit, getCalendar error', error),
(week) => this._$log.debug('Calendar: onInit, getCalendar notify', week)
);
}
/**
*
* #returns {Promisse}
*/
getCalendarGrid(startDay, endDay){
let start = startDay, end = endDay;
let result = this._$q.defer(),
grid = {},
index = 0,
diff = end.diff(start,'d'),
day = {
title: null,
activity: []
},
week = {};
while (diff != 0){
// go through all the days.
day.title = start.format('DD');
angular.extend(week, {[start.format('YYYYMMDD')]: day});
day = {
title: null,
activity: []
};
// put by week
if ((diff % 7 == 1) || diff == 0){
week = { [start.format('YYYYWW')]: week };
angular.extend(grid,week);
result.notify(week);
week = {};
}
start.add(1,'d');
diff = end.diff(start,'d');
}
result.resolve(grid);
return result.promise;
}
}
Console screen
Console screen with errors
I am building an app using google's QPX express and I created a service to call the QPX web service.
I noticed that when I inspect certain functions, I see that they are executing indefinitely. The functions are $scope.pageArray, $scope.humanizeTime.Can someone help me identify why this is the case.
I have an understanding of why this is happening, but am not able to identify the root cause. Somehow/Somewhere in the code I am suggesting to Angular that the model has changed and therefore Angular is running a $scope.$digest, but I cant seem to identify where.
var resultController =planeSearchControllers.controller('resultController',['$scope','$http','commonSharedService','flight', function($scope,$http,commonSharedService,flight){
var isDebugEnabled = true;
$scope.showResults = false;
$scope.showPlaneSearch = true;
$scope.showPlaneError = false;
$scope.planeView = false;
$scope.historyView = false;
$scope.$watch(function() {return commonSharedService.getMode();},function(newValue,oldValue){
console.log('New Mode is' + newValue);
if(newValue == 'plane'){
$scope.planeView = true;
$scope.historyView = false;
$scope.historyObj = [];
}else if(newValue == 'history'){
getHistory(commonSharedService.getUserName());
$scope.planeView = false;
$scope.historyView = true;
}
});
$scope.$watch(function (){return commonSharedService.getValidateInputs();},function (newValue,oldValue){
if(isDebugEnabled){
console.log('Value is changed for getValidateInputs ' + 'New Value is -->'+ newValue);
}
$scope.validateInputs = newValue;
if($scope.validateInputs == true) {
makePlaneCall();
$scope.showResults = true;
commonSharedService.setValidateInputs(undefined);
$scope.errorMsg = commonSharedService.getErrorMsg();
}
if($scope.validateInputs == false) {
$scope.showResults = false;
commonSharedService.setValidateInputs(undefined);
$scope.errorMsg = commonSharedService.getErrorMsg();
}
});
$scope.humanizeTime = function(time){
//var duration = new moment.duration(time, "minutes");
//var hours = duration.hours();
//var minutes = duration.minutes();
var hours = Math.floor(time/60);
var minutes = time - (60 * hours);
var str = hours == 0 ? '': hours + 'hours ' ;
str += minutes == 0 ? '': minutes + 'minutes';
return str;
};
//Page Filtering
$scope.currentPage = 1;
$scope.numPerPage = 5;
$scope.maxSize = 5;
$scope.numPerPage = 5;
$scope.numPages = function () {
if($scope.tripOption!=null )
return Math.ceil($scope.tripOption.length / $scope.numPerPage);
else
return 0;
};
$scope.pageArray = function () {
var input = [];
for(var i=0;i<$scope.numPages();i++){
input[i] = i+1;
}
return input;
};
var paging = function(arrayIn,pageNo,perPageNo){
var outArray = [];
if(arrayIn!=undefined){
var from = perPageNo * (pageNo-1);
var to = from + perPageNo;
if (to > arrayIn.length)
to= arrayIn.length;
//console.log(from);
//console.log(to);
//console.log(outArray);
for (var i =from; i<to ;i++)
outArray.push(arrayIn[i]);
}
return outArray;
};
$scope.paginationFilter = function (){
return paging($scope.tripOption,$scope.currentPage,$scope.numPerPage);
};
var makePlaneCall = function () {
$scope.appendObj = commonSharedService.getAppendObj();
$scope.jsonObj = commonSharedService.getJsonObj();
$scope.jsonObj['time'] = moment().format("ddd Do,YYYY HH:mm a");
var user = commonSharedService.getUserName();
if(user != undefined)
setHistory(user,$scope.jsonObj);
$scope.planeRequest = {};
$scope.requestObj = {};
var slice = [];
var slice1 ={};
var slice2 ={};
var slice3 ={};
{
slice1['origin'] = $scope.appendObj['departAirport'];
slice1['destination']= $scope.appendObj['multiCity'] ? $scope.appendObj['interimAirport'] :$scope.appendObj['arrivalAirport'];
slice1['date']= $scope.appendObj['departureDate'];
slice1['permittedDepartureTime'] ={
"earliestTime": $scope.appendObj['departureEarliest']
};
if($scope.appendObj['preferredCabin']!=undefined){
slice1['preferredCabin'] = $scope.appendObj['preferredCabin'];
}
slice.push(slice1);
}
if($scope.appendObj['multiCity'] == true){
slice2['origin'] = $scope.appendObj['interimAirport'];
slice2['destination']= $scope.appendObj['arrivalAirport'];
slice2['date']= $scope.appendObj['interimDate'];
slice2['permittedDepartureTime'] ={
"earliestTime": $scope.appendObj['interimEarliest']
};
if($scope.appendObj['preferredCabin']!=undefined){
slice2['preferredCabin'] = $scope.appendObj['preferredCabin'];
}
slice.push(slice2);
}
if($scope.appendObj['isReturnFlight'] == 'true'){
slice3['origin']=$scope.appendObj['arrivalAirport'];
slice3['destination'] = $scope.appendObj['departAirport'];
slice3['date']=$scope.appendObj['arrivalDate'];
slice3['permittedDepartureTime'] ={
"earliestTime": $scope.appendObj['arrivalEarliest']
};
if($scope.appendObj['preferredCabin']!=undefined){
slice3['preferredCabin'] = $scope.appendObj['preferredCabin'];
}
slice.push(slice3);
}
for(var property in $scope.jsonObj){
if($scope.jsonObj.hasOwnProperty(property)){
$scope.requestObj[property] = $scope.jsonObj[property];
}
}
$scope.requestObj['slice'] = slice;
//$scope.requestObj['passengers'] = $scope.jsonObj['passengers'];
$scope.requestObj['solutions'] = 5;
$scope.requestObj['refundable'] = false;
$scope.planeRequest['request'] =$scope.requestObj;
flight.search($scope.planeRequest,function(response){
$scope.result= response;
$scope.info = $scope.result.trips.data;
$scope.tripOption = $scope.result.trips.tripOption;
//console.log($scope.tripOption);
if($scope.tripOption!=null){
{
$scope.airport = $scope.info.airport;
$scope.city = $scope.info.city;
$scope.aircraft = $scope.info.aircraft;
$scope.tax = $scope.info.tax;
$scope.carrier = $scope.info.carrier;
$scope.showPlaneError = false;
$scope.paginationFilter();
}
}
else{
$scope.showPlaneError = true;
$scope.planeSearchErrorMsg = "No Solutions found. Please check your airport codes and set more liberal parameter for the search to see if something turns up.";
}
console.log(response);
},function(response){
console.log("error");
$scope.result= response;
console.log(response);
});
};
function setHistory(userName,historyObj){
var firstTime=true;
var ref = new Firebase("http://flight-searchdb.firebaseIO.com/History");
var historyRef = ref.child(userName);
historyRef.on("value", function(historySnapshotObj) {
if(firstTime==true){
var historySnapshot = historySnapshotObj.val();
console.log(historySnapshot);
var count;
if(historySnapshot!=null)
count = historySnapshot['count'];
console.log(count);
var obj ={};
if(count == undefined) {
obj['count'] = 0;
obj[0]= historyObj;
}else if(count < 9){
obj['count'] = ++count;
obj[count]= historyObj;
}else if(count == 9){
console.log(3);
obj['count'] = count;
for(var i=0;i<9;i++)
obj[i+1] = historySnapshot[i];
obj[0] = historyObj;
}
firstTime = false;
historyRef.update(obj);
}
else {
console.log("Wrong Place");
}
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
}
function getHistory(userName){
var ref = new Firebase("http://flight-searchdb.firebaseIO.com/History");
var usersRef = ref.child(userName);
usersRef.on("value", function(snapshot) {
for (var i=0;i<10;i++){}
var userHistory = snapshot.val();
var count;
var array=[];
if(userHistory!=null)
count = userHistory['count'];
if (count!=undefined) {
for (var i=0;i <count ; i++)
array.push(userHistory[i]);
}
$scope.historyObj = array;
$scope.$digest();
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
}
}]);
I tested all functions and all of them seem to be working , except that when I added the pagination I dont see any result.
P.S : I was using a filter before , but for the sake of debug , I moved the pagination logic into the controller. I also understand that I could have used a directive.(since I am displaying the result at only place, I decided to skip it.)
I am also adding the view below , in which I am using the controller.
<!-- Result Body-->
<div class="col-sm-6 col-md-6 col-lg-7" data-ng-controller="resultController">
<div class="container-fluid">
<div data-ng-show="planeView">
<div data-ng-hide="showResults">
<div><span></span><span>{{errorMsg}}</span></div>
</div>
<div data-ng-show="showResults">
<div class="showPlaneSearch" data-ng-show="showPlaneSearch">
<div class="query thumbnail">
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">
<span >Page</span>
<select data-ng-model="currentPage" id="selectPage" class="form-control col-xs-5 col-sm-5 col-md-5 col-lg-5"
data-ng-options="value for value in pageArray()" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="Select Page Number">
</select>
</div>
</div>
</div>
<ul class="planesResult">
{{currentPage}}
{{numPerPage}}
<li ng-repeat="trip in paginationFilter" class="thumbnail">
<div class="row phoneContents">
<!-- Image -->
<div class="hidden-xs hidden-sm hidden-md col-lg-2">
<img src="images/Airplane-Icon.png" />
</div>
<!-- Trip Total $$$ -->
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-10" >
<span class="price">{{trip.saleTotal}}</span>
</div>
<!-- Everything except Image -->
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-10">
<!--Each Slice -->
<div ng-repeat="slice in trip.slice" class="slice row">
<!-- Each Segment Origin-->
<span class="col-xs-hidden col-sm-4 col-md-4 col-lg-4">
<span ng-repeat="segment in slice.segment">
<span > {{segment.leg[0].origin}}--></span>
<span ng-show="$last"> {{segment.leg[0].destination}} </span>
</span>
</span>
<!-- Each Segment Origin-->
<span class="col-xs-12 col-sm-3 col-md-3 col-lg-3">{{humanizeTime(slice.duration)}}</span>
<span ng-repeat="segment in slice.segment" class="col-xs-hidden col-sm-4 col-md-4 col-lg-4">
<span ng-show="$first"> Depart at {{}} </span>
</span>
<br>
</div>
</div>
</div>
</li>
</ul>
</div>
<div class="showPlaneError" data-ng-show="showPlaneError">
<span class="thumbnail">{{planeSearchErrorMsg}}</span>
</div>
</div>
</div>
<div data-ng-show="historyView">
<pre>{{historyObj | json}}</pre>
</div>
</div>
</div>
I can't run code, but i see something suspicious, worth changing:
two places:
$scope.paginationFilter = function (){
return paging($scope.tripOption,
and
if($scope.tripOption!=null){
{
$scope.airport = $scope.info.airport;
$scope.city = $scope.info.city;
$scope.aircraft = $scope.info.aircraft;
$scope.tax = $scope.info.tax;
$scope.carrier = $scope.info.carrier;
$scope.showPlaneError = false;
$scope.paginationFilter();
I see that when tripOption!= null you call paginationFilter function, which uses tripOption.
This is continuation of this question Get other columns from select ng-options
I have the problems with my directive. First problem is that with the very first initial load of the form I can see correctly department and category, but item shows 'Select Item' instead of the item. The second problem is when I navigate to another row in the list, the initial values are not shown (e.g. everything is showing 'Select Department', 'Select Category', 'Select Item' instead of the values. I confirmed that in that situation I didn't retrieve the row's data yet. So, I need to run directive's code only after I got my data.
How can I resolve my problems?
Here is the whole code for the directive:
(function () {
'use strict';
var app = angular.module('sysMgrApp');
app.directive('smDci', ['departmentService', 'categoryService', 'itemService', smDci]);
function smDci(departmentService, categoryService, itemService) {
var directive = {
restrict: 'E',
scope: {
selectedDepartmentId: '=?departmentid',
selectedCategoryId: '=?categoryid',
selectedItemId: '=itemid',
selectedDci: '=?dci'
},
controller: ['$scope', 'departmentService', 'categoryService', 'itemService',
function ($scope, departmentService, categoryService, itemService) {
$scope.selectedDepartmentId = $scope.selectedDepartmentId || 0;
$scope.selectedCategoryId = $scope.selectedCategoryId || 0;
$scope.selectedItemId = $scope.selectedItemId || 0;
$scope.selectedDci = $scope.selectedDci || '';
var init = function () {
$scope.metaData = {};
window.console && console.log('Selected departmentId = ' + $scope.selectedDepartmentId +
' Selected categoryId = ' + $scope.selectedCategoryId + ' Selected ItemId = ' + $scope.selectedItemId);
departmentService.getAllDepartments().then(function (data) {
$scope.metaData.departments = data.departments;
//window.console && console.log('Got all departments...')
});
if ($scope.selectedDepartmentId == 0 && $scope.selectedCategoryId == 0 && $scope.selectedItemId != 0) {
itemService.getItemById($scope.selectedItemId).then(function (data) {
var item = data.item;
if (item != null) {
$scope.selectedItem = item;
$scope.selectedDepartmentId = item.departmeId;
$scope.selectedCategoryId = item.categoryId;
window.console && console.log('Initial selections are about to fire...')
getInitialSelections();
}
});
}
else {
getInitialSelections();
}
};
var getInitialSelections = function()
{
if ($scope.selectedDepartmentId != 0) {
$scope.departmentChanged($scope.selectedDepartmentId);
}
if ($scope.selectedCategoryId != 0) {
$scope.categoryChanged($scope.selectedCategoryId);
}
}
$scope.departmentChanged = function (departmentId) {
if (!departmentId) {
$scope.selectedCategoryId = '';
$scope.selectedItemId = '';
$scop.selectedItem = {};
$scope.selectedDci = '';
}
else
{
categoryService.getCategoriesByDepartmentId(departmentId).then(function (data) {
$scope.metaData.categories = data.categories;
//window.console && console.dir($scope.selectedItem);
});
}
};
$scope.categoryChanged = function (categoryId) {
if (!categoryId) {
$scope.selectedItemId = '';
$scope.selectedItem = null;
$scope.selectedDci = '';
}
else
{
itemService.getItemsByCategoryId(categoryId).then(function (data) {
$scope.metaData.items = data.items;
});
}
};
$scope.itemChanged = function(item)
{
$scope.selectedItemId = item.itemId;
$scope.selectedDci = item.department + item.category + item.item;
}
init();
}],
templateUrl: 'app/templates/smDci'
};
return directive;
}
})();
and its HTML:
<div class="row">
<label class="control-label col-md-2" title="#Labels.dci">#Labels.dci:</label>
<div class="col-md-3">
<select class="form-control" ng-model="selectedDepartmentId" name="department" id="department"
ng-options="d.departmeId as d.descrip for d in metaData.departments"
data-no:dirty-check
ng-change="departmentChanged(selectedDepartmentId)">
<option value="">#String.Format(Labels.selectX, Labels.department)</option>
</select>
</div>
<div class="col-md-3">
<select class="col-md-3 form-control" ng-model="selectedCategoryId" id="category" name="category"
ng-disabled="!selectedDepartmentId"
data-no:dirty-check
ng-change="categoryChanged(selectedCategoryId)"
ng-options="c.categoryId as c.descrip for c in metaData.categories | filter: {departmeId:selectedDepartmentId}">
<option value="">#String.Format(Labels.selectX, Labels.category)</option>
</select>
</div>
<div class="col-md-3">
<select class="col-md-3 form-control" ng-model="selectedItem" id="item" name="item"
ng-disabled="!selectedCategoryId"
ng-change="itemChanged(selectedItem)"
ng-options="c as c.descrip for c in metaData.items | filter: {departmeId:selectedDepartmentId, categoryId:selectedCategoryId}">
<option value="">#String.Format(Labels.selectX, Labels.item)</option>
</select>
<div class="field-validation-error">
<span ng-show="item.$error.required">#String.Format(Messages.isRequired, Labels.item)</span>
</div>
</div>
</div>
<div class="clearfix"></div>
And this is how I use it in the form:
<data-sm:dci itemid="currentCardAct.itemId" dci="currentCardAct.dci"></data-sm:dci>
Using the logging to console I can see that card data retrieved after I need, e.g. in the console I see
Selected departmentId = 0 Selected categoryId = 0 Selected ItemId = 0
CardActController.js:221 Current Card Activity data retrieved..
smDci.js:28 Selected departmentId = 0 Selected categoryId = 0 Selected ItemId = 0
CardActController.js:221 Current Card Activity data retrieved..
I guess I can add watches in the directive's code, but is it the only option?
I solved the problem by adding a watch. I'm now trying to solve the problem with the initial selection of the item and apparently it's a known problem as referenced here http://odetocode.com/blogs/scott/archive/2013/06/19/using-ngoptions-in-angularjs.aspx about initial selection.