Onsen Switch Not Remembering it's State (and Not Calling Function on Switch Checked)? - onsen-ui

I have an Onsen-UI Switch. I switch it on, then navigate away from the page. When I return to the page, the switch has changed to off; the switch has not remembered it's state?
I am also having trouble coding the Switch so it calls a function on Switch changed.
I've read the Onsen Docs and searched online, but I cannot find a clearly coded example to achieve the above.
<label class="switch">
<input type="checkbox" var="switchName" ng-model="switchState" ng-change="switchChanged()" class="switch__input">
<div class="switch__toggle"></div>
</label>
Script
function switchChanged() {
if ($scope.switchState == true) {
// Switch to saving app data into Production Database
} else {
// Switch to saving app data into Developer Database
};
};
Thank you for any help.

ons-switch remembers its state as long as the page that contains it is not destroyed and created again. You can achieve that with pushPage in ons-navigator or with persistent tabs in ons-tabbar.
If you want to listen to ons-switch's change event:
document.addEventListener('change', function(event) {
console.log('Switch value is: ', event.target.checked);
});
You can see it working here: http://codepen.io/frankdiox/pen/JGYZvx
Hope it helps!

You need to store the state or value ng-nodal (maybe in database). then use that value to initialise your switch input.
INITIALISING FROM YOUR STORAGE
Controller
$scope.switchtoggle = value == 1;
$scope.switchTrigger = function (obj){
if(obj){
//Do something
} else {
//Do something else
}
}
in your HTML
<ons-switch ng-model="switchtoggle" ng-change="switchTrigger(switchtoggle)" ></ons-switch>

Related

How to know when angular-busy's cg-busy is actively displaying (or how do I enforce a minDuration for a promise chain)?

I'm using angular-busy on an old angular 1.5.9 codebase (yeah, yeah, we're migrating soon, ...)
I am using it to do a "Check for updates ..." overlay and I want the busy message to show for a bit, so I set delay=0, minDuration=1500 just so it doesn't look like it flickers. The updates generally take < 200ms.
As part of the updates the content of what's in my $uibModal dialog updates and I'm using ng-show to hide it until my call has returned. That part works great. But because I'm using cg-busy's minDuration, the content shows before cg-busy's overlay has left - which I don't want.
cg-busy know's when it's active and not. Internally it uses a child scope for it's tracker class which has a method called $cgBusyIsActive() that it uses for it's own ng-show. It would great if I had access to that, but after researching a bit, alas, I can not find a way to get to it (and probably shouldn't even it I could).
Question 1: Does anyone know of a way to detect when cg-busy is active and use that to ng-show or ng-hide?
Here's a quick snippet showing what I would like:
<div cg-busy="$ctrl.updatesBusy">
<div ng-show="!$cgBusyIsActive() && $ctrl.updateResult.done">
...
</div>
</div>
Question 2: Or are there better/different ways of accomplishing my workaround below of forcing the promise chain to have a minDuration?
To get around this currently, I just create my own timer and shove a timeout in my promise chain that fires if there's any time left in minDuration, but I'd love a solution that uses cg-busy's minDuration.
const cgTimerStarted = Date.now();
$ctrl.updatesBusy.promise = myUpdateCallAsync()
.then(function(result) {
// blah blah, blah blah
return $q.resolve(); // return a promise obj or cg-busy will go away
})
.catch(function(err) {
// boo hoo, boo hoo
return $q.resolve(); // return a promise obj or cg-busy will go away
})
.then(function() {
const minDuration = $ctrl.updatesBusy.minDuration;
const timeTaken = Date.now() - cgTimerStarted;
const timeLeft = Math.max(minDuration - timeTaken, 0);
return $timeout(timeLeft);
})
.finally(function() {
$ctrl.updatesResult.done = true;
});

How can I make my custom JavaScript code work properly in AngularJS MVC?

As a simple example from my custom JavaScript file:
if(document.URL.indexOf("http://localhost/Angular/Angular_Project_01/index.html#!/myinfo") >= 0)
{
alert("you are viewing myinfo page");
}
This will only execute if page is refreshed while in the myinfo view. The problem is this page contains forms that need to be disabled after user has entered his/her information.
This code worked well for me in this project. Not sure if it's best practice though.
window.addEventListener('hashchange', function() {
if(window.location.hash == '#!/myinfo' //&& something)
{
console.log("Hash is #!/myinfo");
setTimeout(function() //Avoid TypeError: Cannot set property 'value' of null
{
//Do something
}, 1000);
}
});

angularjs ng-model in select

im stucked in a dumb problem, but i don't know how to go ahead, so i hope that someone of you can give me a help.
My problem is that i have a list of element, and i can acces for everyone of them, in which i can load the specific data of the element. In this view i can load the data from the REST backend call, and work all prettly, the problem that i have encountered is when i have to load a list with the select tag, and im working with ng-model and ng option. I want to load in that list the data selected that the element have in this moment, but when i try to put in ng-model the data that i give from the backend, that doesnt work, instead if i initialize the same element out of the service call backend that work and i can see the element selected. The service is working because i can see every value of the element, and even if i try to take the specific value i can see it if for example i put that in a paragraph. Thanks in advance.
this is where i load the list:
self.AzionePropostaLista=[
{ qsAzioneProposta:'SENSIBILIZZAZIONE', value: 'SENSIBILIZZAZIONE'},
{ qsAzioneProposta:'INIBIZIONE MANUAL ENTRY', value: 'INIBIZIONE MANUAL ENTRY'},
{ qsAzioneProposta:'INIBIZIONE BANDA', value : 'INIBIZIONE BANDA'},
{ qsAzioneProposta:'INIBIZIONE COMPLETA', value : 'INIBIZIONE COMPLETA'},
{ qsAzioneProposta:'REVOCA', value : 'REVOCA'},
{ qsAzioneProposta:'RINUNCIA', value :'RINUNCIA'},
{ qsAzioneProposta:'SBLOCCO', value :'SBLOCCO'},
{ qsAzioneProposta:'COMUNICAZIONE INTERNA', value :'COMUNICAZIONE INTERNA'},
{ qsAzioneProposta:'AUTOFIN.SOSPETTATO', value : 'AUTOFIN.SOSPETTATO'},
{ qsAzioneProposta:'VALUTATO SENZA RISCHIO', value :'VALUTATO SENZA RISCHIO'}
];
This is the data that im retriving from the backend service:
self.condition: "SENSIBILIZZAZIONE"
MerchantService.getThisAction({qs_key:$routeParams.qs_key,qs_data_proposta:formatData},function(response){
if(response.statusCode==0){
self.action = response.data;
self.condition = response.data.qsAzioneProposta; THIS DOESN'T WORK BUT I CAN SEE THAT VALUE
$log.debug("self.condition is"+self.condition);
}
else {
sweetAlert('Error','something missing or you are trying to acces an inexistent merchant', 'error');
$location.path("/home");
}
});
// self.condition = 'SENSIBILIZZAZIONE' THIS WORK
<div class="input-field col s4">
<select ng-model="$ctrl.condition" ng-options="azione.value as azione.qsAzioneProposta for azione in $ctrl.AzionePropostaLista"></select>
<label>Suggested action</label>
</div>
This is the data that i'm retriving from the backend
Your ng-model aggregates azione.value from ng-options therefore:
Change:
self.condition = response.data.qsAzioneProposta;
to:
self.condition = response.data.value;
DEMO

Using Angular Material, is it possible to close a specific dialog

I have an AngularJS app using the Angular Material UI framework.
The app has different mechanisms showing dialogs (e.g error and loading spinner) and it would be preferable to only close one specifically chosen in certain scenarios, e.g. when an AJAX request is finished fetching data, I would like my loading spinner to close, but not any error dialog that may be the result of the fetching.
What I can find in documentation and code doesn't agree (though code should win the argument):
Documentation says only the latest can be closed, with an optional response
The code says the latest, a number of latest or all open can be closed, with an optional reason
Example in the documentation says a specific dialog can be closed, with a flag denoting how or why
I have made a demo of my intent, as MCV as possible – these are the highlights:
var dialog = {},
promise = {};
function showDialogs(sourceEvent) {
showDialog(sourceEvent, "one");
showDialog(sourceEvent, "two");
}
function showDialog(sourceEvent, id) {
dialog[id] = $mdDialog.alert({...});
promise[id] = $mdDialog.show(dialog[id]);
promise[id].finally(function() {
dialog[id] = undefined;
});
}
function closeDialogs() {
$mdDialog.hide("Closed all for a reason", {closeAll: true});
}
function closeDialogLatest() {
$mdDialog.hide("Closed from the outside");
}
function closeDialogReason() {
$mdDialog.hide("Closed with a reason");
}
function closeDialogSpecific(id) {
$mdDialog.hide(dialog[id], "finished");
}
EDIT:
I know the code always wins the argument about what happens, but I wasn't entirely sure it was the right code I was looking at.
I have updated the examples to better test and illustrate my point and problem. This shows things to work as the code said.
What I'm really looking for is whether it might still be possible to achieve my goal in some other way that I didn't think of yet.
Using $mdPanel instead of $mdDialog I was able to achieve the desired effect; I forked my demo to reflect the changes – these are the highlights:
var dialog = {};
function showDialogs() {
showDialog("one");
showDialog("two");
}
function showDialog(id) {
var config = {...};
$mdPanel.open(config)
.then(function(panelRef) {
dialog[id] = panelRef;
});
}
function closeDialogs() {
var id;
for(id in dialog) {
closeDialogSpecific(id, "Closed all for a reason");
}
}
function closeDialogSpecific(id, reason) {
var message = reason || "finished: " + id;
if(!dialog.hasOwnProperty(id) || !angular.isObject(dialog[id])) {
return;
}
if(dialog[id] && dialog[id].close) {
dialog[id].close()
.then(function() {
vm.feedback = message;
});
dialog[id] = undefined;
}
}
I would suggest having two or more dialogs up at the same time isn't ideal and probably not recommended by Google Material design.
To quote from the docs
Use dialogs sparingly because they are interruptive.
You say:
when an AJAX request is finished fetching data, I would like my
loading spinner to close, but not any error dialog that may be the
result of the fetching.
My solution here would be to have one dialog which initially shows the spinner. Once the request is finished replace the spinner with any messages.

ngChecked doesn't seem to want to bind to the model. Why?

I'm using Ionic and thus angularjs, and I'm trying to store a setting in localStorage.
I've a checkbox that I want to use to set analytics on or off. The html looks like this.
Analytics on/off
<label class="toggle toggle-balanced">
<input type="checkbox" ng-click="toggleAnalytics()" ng-checked="analytics">
<div class="track">
<div class="handle"></div>
</div>
</label>
and in the related controller I have:
$scope.analytics = $localstorage.get('analyticsOnOff');
$log.log("Analytics initialised at", $scope.analytics);
$scope.toggleAnalytics = function(){
if($scope.analytics===true){
$scope.analytics = false;
$localstorage.set('analyticsOnOff', false);
}else{
$scope.analytics = true;
$localstorage.set('analyticsOnOff', true);
}
$log.log("Analytics is ", $scope.analytics);
}
So as you can see, when you change the checkbox the toggleAnalytics() function toggles $scope.analytics between true and false and updates the localstorage to reflect that.
Note that I am using $localstorage methods. $localstorage is defined in another service. It's allows you to set and get localStorage objects easily.
Anyway, my issue is a really simple, but baffling one. I know I can alter the analytics value from the console logs, but no matter what I do the checkbox initialises as on.
Any ideas?
You should be using ng-model on your checkbox, this will handle setting the actual property - and you can use a change event then:
<input type="checkbox" ng-change="toggleAnalytics(analytics)" ng-model="analytics" />
And the controller:
$scope.toggleAnalytics = function(isChecked) {
$localstorage.set('analyticsOnOff', isChecked);
$log.log("Analytics is ", isChecked);
}
Thank you very much for the feedback guys.
#nickgraef for altering me to the real problem - that .get() returns a string.
#tymeJV for supplying me with a much more elegant version of my own code.
This is what I did in the end, it's a mash up of both tips. I convert the analytics variable into a boolean straight after I .get() it from localstorage.
$scope.analytics = $localstorage.get('analyticsOnOff');
$scope.analytics = ($scope.analytics == 'true' ? true : false);
$log.log("Analytics initialised at", $scope.analytics);
$scope.toggleAnalytics = function(isChecked) {
$localstorage.set('analyticsOnOff', isChecked);
$log.log("Analytics is ", isChecked);
}

Resources