This question my seems silly to you but i just want to know that is it possible to show ionic loader in between the process of rendering data in dropdown by ng-repeat.I goggled and found two directives one is for after-render and other is for on-finish-render both works good but i am really confused that how can i show and hide my ionic loader during this whole process.
here is some of my code :-
<label class="item item-input"> <select class="input-select"
ng-model="user.country.value"
ng-change="selectedCountry(user.country.value)">
<option ng-selected="country.value==user.country.value"
ng-repeat="country in results" value="{{country.value}}">
{{country.name}}</option>
<option value="" disabled hidden>{{'checkoutPage.country' |
translate}}</option>
</select>
</label>
<label class="item item-input" ng-if="showDropDownInStateLabel()">
<select class="input-select" ng-model="userState.states.region_id"
ng-change="selectedState(userState.states.region_id)">
<option ng-selected="states.region_id==userState.states.region_id" ng-repeat="states in StatesArray" on-finish-render="ngRepeatFinished"
value="{{states}}">{{states.name}}</option>
<option value="" disabled hidden>{{'checkoutPage.state' |
translate}}</option>
</select>
</label>
here is directive :-
app.directive('onFinishRender', function($timeout) {
return {
restrict : 'A',
link : function(scope, element, attr) {
if (scope.$last === true) {
$timeout(function() {
scope.$emit('ngRepeatFinished');
});
}
}
}
});
here is the listener for event:-
$scope.$on('ngRepeatFinished', function(
ngRepeatFinishedEvent) {
alert("rendering ends here");
});
can any one tell me that how to show loader to user when ng-repeat rendering the data in dropdown.I even try by making two different functions for showloader() and hideloader() . showLoader i call when user select some value in dropdown and hideLoader gets call in $scope.$on function.
Actually i am having two dropdowns one is for countries and other is for their respective states.When user select country that state dropdown got visible to user.this whole process took some time in rendering which make application looks like hanged to user so i just want to display user a loader to avoid this illusion.
here is the function which finds which country have states array and according to which stats dropdown got visible to user :-
$scope.user = {};
$scope.selectedCountry = function(value) {
// alert(value);
$scope.data.region = '';
if (angular.isString(LocalStorage
.getData("StateSelected"))) {
LocalStorage.setData("StateSelected", "");
LocalStorage.setData("Statename", "");
}
if (angular.isString(LocalStorage
.getData("Addressregion"))) {
LocalStorage.setData("Addressregion", "");
}
$scope.user.country_id = value;
LocalStorage.setData("CountrySelected", value);
for ( var c = 0; c < LocalStorage
.getObject("getCountriesresult").length; c++) {
if (value == LocalStorage
.getObject("getCountriesresult")[c].value) {
if (LocalStorage
.getObject("getCountriesresult")[c].state.length > 0) {
shouldShowDropdown = true;
$scope.StatesArray = LocalStorage
.getObject("getCountriesresult")[c].state;
} else {
shouldShowDropdown = false;
}
}
}
}
Any help will be appreciated,
Thanks
This kind of feature should never take so long to execute.
I think you should try to remove the huge amount of LocalStorage access inside loops. From what I saw, you can do everything you want using local variables (in-memory).
$ionicLoading works fine for async calls that take time, like an AJAX call.
Related
I'm trying to filter my Gantt Chart using a drop-down checkbox list. this is my code
index.html
<label class="text-primary" for="department">Select by Departments: </label>
<select id="department" style="width:200px; height:20px; " mode="checkbox">
<option value="ALL" selected="1" >ALL</option>
<option value="ARTIST">ARTIST</option>
<option value="ADMIN">ADMIN</option>
<option value="LEAD">LEAD</option>
<option value="HR">HR</option>
<option value="PRODUCTION">PRODUCTION</option>
<option value="MANAGEMENT">MANAGEMENT</option>
<option value="TECHNOLOGY">TECHNOLOGY</option>
</select>
function
<script>
var myCombo;
function checkbox_department() {
myCombo = dhtmlXComboFromSelect("department");
myCombo.attachEvent("onCheck", function(value, state){
gantt.attachEvent("onBeforeTaskDisplay", function (id, task) {
var department_value = value
if (task.job_category == department_value || department_value == 'ALL') {
console.log(value);
return true;
}
});
gantt.render();
});
}
</script>
the job_category came from a JSON file.
so far I manage to filter the gantt chart with any first checkbox I checked but when I check another checkbox, let say i check artist and production everything disappear and in the console log it'll display
3PRODUCTION
7ARTIST
2PRODUCTION
52ARTIST
PRODUCTION
51ARTIST
2PRODUCTION
3ARTIST
PRODUCTION
22ARTIST
It will turn out like that, it would be easier if i just print screen the whole thing here but I'm using my office desktop and file uploading is blocked. Can anyone help me solves this issue, thanks in advance
Your combo adds an onBeforeTaskDisplay handler each time user checks combo value, while never removing previously added handlers when an option becomes unchecked/unselected.
I'd suggest to store combobox selection in some scope variable and declare only one onBeforeTaskDisplay handler which will filter gantt by the value of that variable.
Then, inside onCheck handler of combo you update a scope variable with the selection state of the combo and call gantt repaint in order to invoke filtering
Your code may look following:
var myCombo;
function checkbox_department() {
var department_value = 'ALL';
myCombo = dhtmlXComboFromSelect("department");
myCombo.attachEvent("onCheck", function(value, state){
department_value = value;// put combo value into scope variable
gantt.render();// and repaint gantt
});
// filter gantt by value of the scope variable
gantt.attachEvent("onBeforeTaskDisplay", function (id, task) {
if (task.job_category == department_value || department_value == 'ALL') {
console.log(value);
return true;
}
});
}
and here is a simplified demo in case i got something wrong with the explanation and code sample
http://docs.dhtmlx.com/gantt/snippet/b6053d50
Update:
If you have a multiselect combo, you may need a bit different code. Something following should work:
var myCombo;
function checkbox_department() {
var department_value = {'ALL': true};
myCombo = dhtmlXComboFromSelect("department");
myCombo.attachEvent("onCheck", function(value, state){
var values = myCombo.getChecked();
department_value = {};// put combo value into scope variable
for(var i = 0; i < values.length; i++){
department_value[values[i]] = true;// build hash for easy check later
}
gantt.render();// and repaint gantt
});
// filter gantt by value of the scope variable
gantt.attachEvent("onBeforeTaskDisplay", function (id, task) {
if(department_value['ALL'])
return true;
return !!department_value[task.job_category];
});
}
I have hundreds of cases like this (so the fix would have to be global and not tied to just this particular example)
There is a lot of select boxes like this:
<select ng-model="selectedItem">
<option ng-repeat="item in items | filter:attributes" value="{{item.id}}">{{item.name}}</option>
</select>
The selectedItem variable is null (and it will always initialize as null, which can't be changed in the controller in this particular situation).
What I'm trying to figure out is a way to globally watch all <select> elements in a view, see if the ng-model variable for that <select> box is null and if it is null set it to the first valid option in that select box, anytime the scope changes it will need to check if the ng-model is null and auto-select the first valid option.
The key thing to realise with this is that you can define more than one Angular directive with the same name, and all of them will be run for matching elements.
This is very powerful, as it enables you to extend functionality of built-in directives, or third party ones, etc.
Using this, I was able to create a select directive that would select the first valid option in the list whenever the model value is null.
One thing it doesn't do, however, is cope if you remove the selected item from the list (it goes back to being blank). But hopefully it is enough to get you started.
var app = angular.module('stackoverflow', []);
app.controller('MainCtrl', function($scope) {
$scope.selectedItem = null;
$scope.items = [1, 2, 3, 4].map(function(id) {
return {
id: id,
visible: true,
text: 'Item ' + id
};
});
});
app.directive('select', function() {
return {
restrict: 'E',
require: '?ngModel',
link: function($scope, $elem, $attrs, ngModel) {
// don't do anything for selects without ng-model attribute
if (!ngModel) return;
// also allow specifying a special "no-default" attribute to opt out of this behaviour
if ($attrs.hasOwnProperty('noDefault')) return;
// watch the model value for null
var deregWatch = $scope.$watch(function() {
return ngModel.$modelValue;
}, function(modelValue) {
if (modelValue === null) {
// delay to allow the expressions to be interpolated correctly
setTimeout(function() {
// find the first option with valid text
var $options = $elem.find('option'),
$firstValidOption, optionText;
for (var i = 0, len = $options.length; i < len; i++) {
optionText = $options.eq(i).text();
if (optionText !== '' && !optionText.match(/^(\?|{)/)) {
$firstValidOption = $options.eq(i);
break;
}
}
if ($firstValidOption) {
$firstValidOption.prop('selected', true);
ngModel.$setViewValue($firstValidOption.attr('value'));
// trigger a digest so Angular sees the change
$scope.$evalAsync();
}
}, 0);
}
});
// clean up in destroy method to prevent any memory leaks
var deregDestroy = $scope.$on('$destroy', function() {
deregWatch();
deregDestroy();
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app="stackoverflow">
<div ng-controller="MainCtrl">
<select ng-model="selectedItem">
<option ng-repeat="item in items | filter:{visible:true} track by item.id" value="{{item.id}}">{{item.text}}</option>
</select>
<p>Visible items:</p>
<ul>
<li ng-repeat="item in items track by item.id">
<label>
<input type="checkbox" ng-model="item.visible">{{item.text}}
</label>
</li>
</ul>
</div>
</div>
I have three select menu that bind to each other and want to set selected value of two select menus. Value that I want to set comes with scope. I try ng-init but that didn't work. Working Plunker
<select ng-init="selManga=direk" ng-model="selManga" ng-options="manga.seri for manga in mangas">
<option value="">Select a Manga</option>
</select>
<select ng-init="selChapter=bacanak" ng-show="selManga" class="browser-default" ng-model="selChapter" ng-options="+idx as chapter.klasor for (idx, chapter) in selManga.randomword">
<option value="">Chapter</option>
</select>
<select ng-show="selManga.randomword[selChapter].yol" class="browser-default" ng-model="selPage" ng-options="+idx as (+idx + 1) for (idx, page) in selManga.randomword[selChapter].yol">
<option value="">Page</option>
</select>
Javascript:
.controller('nbgCtrl',function ($scope, MMG, $stateParams) {
$scope.direk = $stateParams.seri;
$scope.bacanak = $stateParams.klasor;
MMG.adlar.success(function(loHemen) {
$scope.mangas = loHemen;
});
$scope.next = function (manga, chapter, page) {
var nextPage = page + 1;
if (angular.isDefined(manga.randomword[chapter].yol[nextPage])) {
$scope.selPage = nextPage;
} else if (angular.isDefined(manga.randomword[chapter + 1])) {
$scope.selChapter = chapter + 1;
$scope.selPage = 0;
}
}
})
To extract the values for the manga,chapter and page from the url you should use the $routeParams object, which your module should include ngRoute.
I've prepared an example here it might not be obvious but if you download the code and run it in your own browser you can access routes like Manga/Naruto/ch/100 from the url bar.
Once you've restructured your application to use routes and routeParams, in my example I directly bind the chapter and page I get from the url to the view but if you bind them to the models of your dropdowns the dropdowns will update.
$scope.params = $routeParams;
$scope.selManga = $scope.params.bookId
This does not update the url as you select from the dropdown.
In your code you have assign direk and bacanak value more than one times which can cause issue. Set variable property only once.
$scope.direk = $stateParams.seri;
$scope.bacanak = $stateParams.klasor;
$scope.direk = $stateParams.xy; //Remove if not required
$scope.bacanak = $stateParams.xz; //Remove if not required
Set selManga value from $stateParams instead of setting it to direk
$scope.selManga = $stateParams.seri; // Set selManga from $stateParams
$scope.selChapter = $stateParams.klasor; // Set selChapter from $stateParams
The reason why ng-init="selManga=direk" not work is because Syntax error: ng-init="selManga=direk" should be ng-init="selManga='direk'" but after making syntax correct, dropdown will not set because of ng-repeat. ng-init set value to model but at time of setting value ng-repeat doesn't complete setting value for options so selManga set from ng-init not update option to dropdown.
I have a dynamic html block for which a user can add multiple select lists. I'm wanting to disable the selections that the user has made in the previous lists by checking using a custom filter. The part i'm struggling with how to pass the dynamic model into the filter and check that the value does not exist on the already generated select lists.
I've created a plunker. I appreciate the help.
<body ng-app="app" ng-init="things=[{id:0,name:'thing1'},{id:1,name:'thing2'},{id:2,name:'thing3'},{id:3,name:'thing4'}]">
<select ng-model="fields.option1" ng-options="thing.name for thing in things | excludeFrom:fields.option2"></select>
<select ng-model="fields.option2" ng-options="thing.name for thing in things | excludeFrom:fields.option1"></select>
<select ng-model="fields.option2" ng-options="thing.name for thing in things | excludeFrom:fields.option1,fields.option2"></select>
angular.module('app',[])
.filter('excludeFrom', [function () {
return function (things, selectedValue) {
if (!angular.isUndefined(things) && !angular.isUndefined(selectedValue)) { //&& selectedValue.length > 0) {
var tempThings = [];
angular.forEach(selectedValue, function (name) {
angular.forEach(things, function (things) {
if (angular.equals(things, selectedValue.name)) {
tempThings.push(things);
}
});
});
return tempThings;
} else {
return things;
}
};
}]);
There is actually a predefined Angular feature that does what you want to do. A filter in Angular can be negated, which means that you can specifically exclude options from your selection. I recommend using ng-init on your selects though, otherwise you might run into undefined filter options.
Here is some code displaying my solution:
<select ng-model="select1" ng-init="select1 = things[0]" ng-options="thing.name for thing in things | filter:{name:'!'+select2.name}"></select>
<select ng-model="select2" ng-init="select2 = things[1]" ng-options="thing.name for thing in things | filter:{name:'!'+select1.name}"></select>
And here is a plnkr showing it in action.
For further reading on filters you might want to check out the API here
You can also handle the select part as an Array like so
<select ng-model="select[0]" ng-init="select[0] = things[0]"
ng-options="thing.name for thing in things | filter:{name:'!'+select[1].name}"></select>
<select ng-model="select[1]" ng-init="select[1] = things[1]"
ng-options="thing.name for thing in things | filter:{name:'!'+select[0].name}"></select>
However if you want to have a dynamic selection, you will have to write a custom filter which i did like so:
Filter:
.filter('exclude', [function () {
return function(input,select,selection){
var newInput = [];
for(var i = 0; i < input.length; i++){
var addToArray=true;
for(var j=0;j<select.length;j++){
if(select[j].name===input[i].name){
addToArray=false;
}
}
if(addToArray || input[i].name === selection.name){
newInput.push(input[i]);
}
}
return newInput;
};
And usage:
<div ng-repeat="sel in select">
<select ng-model="select[$index]" ng-init="sel"
ng-options="thing.name for thing in things | exclude:select:sel"></select>
</div>
And here is a plunkr showing this solution.
I have a cshtml file in which i have following code (a dropdown with data taken from a model)
<div class="controls">
<select ng-model="model.CountryCode" ng-change="countryChanged({{country.ISO316613LetterCode}})">
<option ng-repeat="country in model.Countries" value="{{country.ISO316613LetterCode}}">{{country.CommonName}}</option>
</select>
</div>
And i have this function, in which i detect that a country was chosen from the dropdown
$scope.countryChanged = function(){
var countryDet = _.find($scope.model.CountryDetails, function(cd){
console.log("countryDet");
return cd.CountryCode === $scope.model.Country;
});
if(countryDet){
$scope.model.CountryDetail = countryDet;
// set business properties from country details
$scope.model.DateFormat = countryDet.DefaultDateFormat;
$scope.model.ShortDateFormat = countryDet.DefaultShortDateFormat;
$scope.model.DateFormatJs = countryDet.DefaultJsDateFormat;
$scope.model.LongDateFormat = countryDet.DefaultLongDateFormat;
$scope.model.TaxCode = countryDet.SalesTaxName;
$scope.model.Currency = countryDet.DefaultCurrencySign;
$scope.model.AccSoftwareDateFormat = countryDet.DefaultAccSoftwareDateFormat
$scope.model.WeightSystem = countryDet.DefaultWeightSystem
}
$scope.loadStates();
};
And another function, that should display additional dropdown on web, showing states if the country choosen was USA or AUstralia
$scope.stateVisible = function(){
if($scope.model && $scope.model.CountryDetail){
return $scope.model.CountryDetail.StateVisible;
}
return false;
};
My problem is, that i do not know how to send the selected LetterCode (value of option) to function countryChanged, because, i thought if i do so, then i will be able to easilly load the states into the additional dropdown and show it on site.
Simply use ng-options which will assign the selected model to the ng-model for the <select>. For example
<select ng-model="model.selectedCountry" ng-change="countryChanged()"
ng-options="country.CommonName for country in model.Countries track by country.ISO316613LetterCode">
</select>
Then, your countryChanged() function (and any other controller function) can use $scope.model.selectedCountry which will be a full country object.
Plunker demo ~ http://plnkr.co/edit/tFjvT92B1itmwkRjZIbJ?p=preview
Since you're using $scope for every variable you could use rootScope
https://docs.angularjs.org/api/ng/service/$rootScope
for passing the data.