Issue with the $mdDialog.show(confirm), not able to execute the code below this dialog directives in AngularJS - angularjs

I'm finding this issue with $mdDialog.show(confirm), the code below the dialog function executes even before the popup arise.
I can handle by setting a flag to restrict the execution of below code. but after the completion of the dialog activity it goes to Error(ie, resolvePromise()) without executing the below code:
//This is the code I have used.
var confirm = $mdDialog.confirm()
.title('Early Dispatch Date Available.')
.textContent('Do you want to reschedule and Change Quantity.')
.ariaLabel('day')
.ok('Yes')
.cancel('Plan on Date');
$mdDialog.show(confirm).then(function (obj)
{
$scope.targetDates[lastItem].Qty = 0;
return;
}, function () {
condition = 'QtyLessThanCap';
});
//for example,this is the code which gets executed even before the comfirmation dialog pops up..
angular.forEach($scope.targetDates, function (Datess)
{
totalCalQty = totalCalQty + parseInt(Datess['Qty']);
});
I want the codes to be executed in the order I have coded them,I mean the below code need to be executed only after the confirmation dialog activity.
Thank you in advance.

The only way I've been able to deal with the same type of functionality is by splitting the function, so for example you have an action function that determines whether you need a modal or can just calculate the total:
function something() { // if modal show modal.then(doSomething) }
then the actual calculation function which can be called directly, or from any level of mdModal.then():
function doSomething() { // calculate total }
It's probably not as pretty as you're looking for but it works.

Related

Why does HTML output not run in a loop the same as a Prompt Response or Alert?

I currently have column A in the spreadsheet filled with checkboxes and have getA1Notation() used to grab this action when the user checks a box. I would then like to run an HTML dialog that has buttons to create an action for that row (HTML script not created yet, just running this test).
The issue I am running into is that when I put the HTML dialog box into a loop, it does not appear when the action (clicking on the checkbox) is done. I can replace the HTML dialog box with a prompt response or alert with buttons and it works perfect, but I would like to use an html box to have multiple custom buttons.
I am very new to using Apps Script for spreadsheets, so thank you for any help.
CODE:
function onEdit(e) {
for (var counter = 0; counter <= 500; counter = counter + 1)
{
const a1 = SpreadsheetApp.getActiveSheet().getRange(2+counter, 1).getA1Notation();
if (e.range.getA1Notation() == a1)
{
SpreadsheetApp.getActiveSheet().getRange(2+counter, 15).setValue('Hello'); //this is just to test the loop is working and doing this action anytime I click a checkbox
var tester = HtmlService.createHtmlOutput("<p>test</p").setWidth(250).setHeight(300);
SpreadsheetApp.getUi().showModelessDialog(tester, "teest");
}
}
}
Assign a function to each row
function onMyEdit(e) {
const sh = e.range.getSheet();
if(sh.getName() == "your sheet name" && e.range.rowStart < rowactions.length) {
const rowactions = ["","funk1","funk2","funk3"];//assigned functions
executeFunctionByName(rowactions[e.range.rowStart])
}
}
function executeFunctionByName(func) {
this[func]();
}
Probably need an installalble onedit.
Just stop, don't use a simple trigger that use a loop to show a dialog / sidebar.
The above because simple triggers have limitations, i.e. they have a shorter execution time limit, and they can't do some things that a function called from button / custom menu can do. They might be able to do certain tasks when the spreadsheet owner activates a trigger that might not work when a editor do the same.
By the other hand, SpreadsheetApp.getUi().showModelessDialog(tester, "teest"); is asynchronous, meaning that after executing this statement the runtime will execute the next one immediately, it will not wait for the Google Sheets UI to load the dialog.
Related
Creating a Dialog Prompt Box from an onEdit Function isn't working

How to invoke a function at a trigger point?

When a trigger point is reached, I just want to call a function or run a few statements to do something, which has nothing to do with interface. Here is how I am doing now for this purpose:
var scene = new ScrollMagic.Scene({triggerElement: "#some-trigger", triggerHook: 'onLeave', offset: })
.on('start', function () {
// statements go here
}).addTo(controller);
Is this the correct way?
The reason to ask this question is that I find out Scroll Magic can be a UNIQUE event control tool.
Little later but I jump to that question because I had the same issue in some projects.
So i solved in two ways:
Using enter or progress event
ENTER is trigger when a scene is starting. It's depends on triggerHook
scene.on("enter", function (event) {
console.log("Scene entered.");
});
PROGRESS is trigger every time
scene.on("progress", function (ev) {
if( ev.progress > 0.25){
//== going farward
}
if(ev.progress < 0.25){
//== going backward
}
})

$scope variable is undefined when it is set inside a function

I have the following example code in my learning app. The service does his job and pulls some data out of a page with json code generated by php, so far so good.
service:
(function() {
'use strict';
angular
.module('app.data')
.service('DashboardService', DashboardService);
DashboardService.$inject = ['$http'];
function DashboardService($http) {
this.getFormules = getFormules;
////////////////
function getFormules(onReady, onError) {
var formJson = 'server/php/get-formules.php',
formURL = formJson + '?v=' + (new Date().getTime()); // Disables cash
onError = onError || function() { alert('Failure loading menu'); };
$http
.get(formURL)
.then(onReady, onError);
}
}
})();
Then i call the getFormules function in my controller and put all the data inside my $scope.formuleItems and test if everything succeeded and 'o no'... $scope.formuleItems = undefined! - Strange because my view is showing data?
part of the controller:
dataLoader.getFormules(function (items){
$scope.formuleItems = items.data;
});
console.log('+++++++++++++++++', $scope.formuleItems); // gives undefined
The first thing i did was search around on stackoverflow to look if someone else had the same issue, and there was: Undefined variable inside controller function.
I know there are some walkarounds for this, i've done my own research, but something tells me that this (see example below) isn't the best way to solve this problem.
solution one: put $watch inside of the controller
$scope.$watch('formuleItems', function(checkValue) {
if (checkValue !== undefined) {
//put the code in here!
}
}
or even:
if($scope.formuleItems != null) {}
The rest of the controller is relying on $scope.formuleItems. Do i really have to put everything into that $watch or if? Can i fix this with a promise? I never did that before so some help would be appreciated.
The code in your callback
function (items){
$scope.formuleItems = items.data;
}
is evaluated asynchronously. That means you first fire the request, then javascript keeps on executing your lines of code, hence performs
console.log('+++++++++++++++++', $scope.formuleItems); // gives undefined
At this point the callback was not invoked yet, because this takes some time and can happen at any point. The execution is not stopped for this.
Therefore the value of $scope.formuleItems is still undefined, of course.
After that - at some not defined time in the future (probably a few milliseconds later) the callback will be invoked and the value of $scope.formuleItems will be changed. You have to log the value INSIDE of your callback-function.
You urgently have to understand this concept if you want to succeed in JavaScript, because this happens over and over again :)

Sometimes svg chart doesn't fit in the container but it works when screen refresh

Sometimes svg chart appear more small than normal. This problem is solved Reloading Screen.
//Values Graphic
$scope.$watch(vm.dataGraphic.watch, function () {
var data = vm.dataGraphic.watch ? $scope.$eval(vm.dataGraphic.watch) : vm.dataGraphic;
setTimeout(sleep,500); //patch to "solve" this issue
function sleep(){
vm.dataValues = getDataValues(data);
}
});
function getDataValues(data) {
vm.dataGraphic = data || dataGraphicTest;
if (vm.dataGraphic.values.length == 0) {
return [];
} else {
vm.dataKeyValues = transformForKeyValues(vm.dataGraphic.values, vm.dataGraphic.accumulated);
vm.barValues = transformBarValues(vm.dataGraphic.values, vm.dataGraphic.limit);
var lineValues = transformLineValues(vm.barValues, vm.dataGraphic.limit, vm.dataGraphic.accumulated, vm.dataGraphic.startMonthlyLimit);
vm.maxY = calculateMaxY(vm.barValues, lineValues);
return [
{
"key": vm.dataGraphic.labelX.name,
"bar": true,
"color": _graphicsColors.bar,
"values": vm.barValues
},
{
"key": _graphicsValorPorDefecto,
"color": _graphicsColors.line,
"values": lineValues
}
];
}
}
SVG element with the following html tags appears with wrong dimensions.
<g class="nvd3 nv-wrap nv-linePlusBar" transform="translate(35,10)">
This problem does not always happen, but when it happens is arranged refreshing the screen.
I think this patch is a bad idea and I would like to understand what is happening .
Thanks
I think your problem ultimately stems from your watch:
$scope.$watch(vm.dataGraphic.watch, function () {
var data = vm.dataGraphic.watch ? $scope.$eval(vm.dataGraphic.watch) : vm.dataGraphic;
setTimeout(sleep,500); //patch to "solve" this issue
function sleep(){
vm.dataValues = getDataValues(data);
}
});
The problem I see is that you're using setTimeout to call your sleep function a half second after the watch fires. As it is now, this will be fine if your $digest is still running in 500ms. setTimeout is a vanilla JavaScript function, so calling it won't notify angularjs that there are any changes after the $digest has ended. Angular only triggers a $digest after 'user-initiated' events like ajax, clicks, entering data, etc. (read more here). If the $digest is running, you'll get lucky and angularjs will just happen to see those changes. You'll need to inform angular of your changes using $scope.$apply:
$scope.$watch(vm.dataGraphic.watch, function () {
var data = vm.dataGraphic.watch ? $scope.$eval(vm.dataGraphic.watch) : vm.dataGraphic;
setTimeout(sleep,500); //patch to "solve" this issue
function sleep(){
vm.dataValues = getDataValues(data);
$scope.$apply();
}
});
There are a lot of ways to use $scope.$apply, so be sure to check out the documentation. Also do a search on something like 'when to use $scope.$apply' and you'll find a lot of people for and against it. It does trigger another $digest loop, which can be costly if you have a lot of bindings or if you're at the end of the final digest loop and apply causes it to start over.
I don't think it's actually a good idea to be updating your model using setTimeout from within a watch function. Does this not work without it? You may have some other async code that needs to be applied in the same fashion. Generally, you want $scope.$apply to be as close to the non-angular asynchronous code as possible.

Make Protractor wait for an alert box?

I am writing E2E tests for a log in page. If the log in fails, an alert box pops up informing the user of the invalid user name or password. The log in itself is a call to a web service and the controller is handling the callback. When I use browser.switchTo().alert(); in Protractor, it happens before the callback finishes. Is there a way I can make Protractor wait for that alert box to pop up?
I solved similar task with the following statement in my Protractor test:
browser.wait(function() {
return browser.switchTo().alert().then(
function() { return true; },
function() { return false; }
);
});
In general, this code constantly tries to switch to an alert until success (when the alert is opened at last). Some more details:
"browser.wait" waits until called function returns true.
"browser.switchTo().alert()" tries to switch to an opened alert box and either has success, or fails.
Since "browser.switchTo().alert()" returns a promise, then the promise either resolved and the first function runs (returns true), or rejected and the second function runs (returns false).
You may use the ExpectedConditions library now, which makes the code more readable:
function openAndCloseAlert () {
var alertButton = $('#alertbutton');
alertButton.click();
// wait up to 1000ms for alert to pop up.
browser.wait(protractor.ExpectedConditions.alertIsPresent(), 1000);
var alertDialog = browser.switchTo().alert();
expect(alertDialog.getText()).toEqual('Hello');
alertDialog.accept();
};

Resources