Problems with escape key to close Angular modal - javascript

I have a component Escrituracao to keep tab of a client's bills. It has this mat-table to show all the proper data. To create a new bill a modal, CadastrarLancamentoComponent, is opened:
openModalLancamento(data) {
const modalOptions: NgbModalOptions = {};
modalOptions.backdrop = 'static';
const modalRef = this.modalService.open(CadastrarLancamentoComponent, modalOptions);
modalRef.result.then((result) => {
if (result) {
this.getLancamentosByPeriod();
}
}, (result) => {
if (result) {
//escape result enters here
this.getLancamentosByPeriod();
}
});
}
When a new bill is added the modal is kept open to add more bills (that's intended). However, when closed with the close or cancel button, if a bill was added, the modal returns a specific result value enabling the page to refresh (thus calling this.getLancamentosByPeriod();). When using cancel or close button with no bill added, it only closes the modal without reloading.
My main struggle is when using the Escape key. When used, both when added or not a bill, it only closes the modal. The result is the same for both situations. I've tried using some Output data transfer to the Financeiro component to say a bill was added; and tried accessing the modal's data to fetch a boolean that would give me that information. All with no solution.
Is there a way to force a value on this modal result when closed with the escape key? Or to send this information proper (like used on the other close buttons) to the main page? What I need is the page to behave the same as the other closing buttons, to reload on close when a bill was added.
I'm using Angular/Typescript for this project.

Are you using material for your dialog, custom, or something else?
If it's material, then I believe there's and option to disable escape being used to close it.
Yeah, looked it up, disableClose is the option. That removes escape and clicking outside of the dialog as ways to close it.
Once disabled, put your own escape key listener in there - something like this I guess - and when escape is detected, directly call your desired, custom close method.

Related

Tab order on prompt page

Using Cognos Analtyics 11.1.7IF9.
I have a user who, oddly enough, wants Cognos to make his workflow more efficient. (The nerve!) He thinks that if he can use the TAB button to navigate a prompt page, he'll be faster because he never needs to reach for the mouse.
To test this I created a simple report with a very simple prompt page using only textbox prompts. As I tab I notice it tabs to everything in the browser: browser tabs, the address bar, other objects in Cognos, ...even the labels (text items) I created for the prompts. Oh... and yes, at some point focus lands on a prompt control.
Within Cognos, I see that the tab order generally appears to be from the top down. (I haven't tried multiple columns of prompts in a table yet.) I must tab through the visual elements between the prompts. Also, while value prompts get focus, there is no visible indication of this.
Is there a way to set the tab order for the prompts on a prompt page?
Can I force it to skip the non-prompt elements?
Can the prompts be made to indicate that they have focus?
I tagged this question with javascript because I figure the answer will likely involve a Custom Control or a Page Module.
Of course, then I'll need to figure out how all this will work with cascading prompts and conditional blocks.
I found a similar post complaining about this being a problem in Cognos 8. The answer contains no detail. It just says to go to a non-existent web page.
I had the same frustration as your user and I made a solution a while back that could work for you. It's not the most elegant javascript and I get a weird error in the console but functionally it works so I haven't needed to fix it.
I created a custom control script that does 2 things on a prompt page.
First, it removes the ability to "select" text item elements on the page. If you only have text items and prompts on the page it sets it's "Tabindex" to "-1". This allows you to tab from one prompt field to the next without it selecting invisible elements or text elements between prompts.
Secondly, if you press "Enter" on the keyboard it automatically submits the form. I am pasting the code below which you can save as a .js and call it in a custom control on a prompt page. Set the UI Type to "None"
define( function() {
"use strict";
function AdvancedControl()
{
};
AdvancedControl.prototype.initialize = function( oControlHost, fnDoneInitializing )
{
function enterSubmit (e)
{
if(e.keyCode === 13)
{
try {oControlHost.finish();} catch {}
}
};
function setTab () {
let nL = [...document.querySelectorAll("[specname=textItem]")]
//console.log(nL)
nL.forEach((node) =>{
node.setAttribute('tabindex','-1')
})
};
setTab();
let exec_submit = document.addEventListener("keydown", enterSubmit, false);
try {exec_submit;} catch {}
fnDoneInitializing();
};
return AdvancedControl;
});

How to re-open Bootstrap modal accidentally closed

I have a few different modals on a page, and it all works as it should, but if a user makes some input on form fields in a modal and then accidentally clicks outside of the modal (which closes it), they loose their changes, since if the user clicks the same button they pressed to open the modal, the data they entered will be overwritten with data pulled from the database.
So I'd like to have a function for "reopen last closed modal" that simply shows the modal again in it's last used state - with whatever data was in it.
Essentially like a Ctrl-Z for accidentally closing a modal.
It's really simple if you know the ID of the modal. Such as:
$('#myModal1').modal('show'); });
But because I have several different modals available on a page, and I don't want to have a bunch of "restore" buttons, I need to be able to detect the ID of the last closed modal.
If there's not a simpler way, I could capture the ID each time a modal is closed, and then use that ID if the modal needs to be reopened without changing its data. Something like this:
$('#myModal1').on('hidden.bs.modal', function (e) {
var LastModal = '#myModal1';
})
$('#myModal2').on('hidden.bs.modal', function (e) {
var LastModal = '#myModal2';
})
function reOpen() {
$(LastModal).modal('show');
}
But I'm guessing there's a way that's simpler and doesn't require me to state all my modals ID's in JS/jQuery. Any ideas?
I've made a few tweaks, and this is working well for me now, with essentially no other hassle than a few short lines of code in my script file.
var LastModal;
$('.modal').on('hidden.bs.modal', (e) => {LastModal = $(e.target).attr('id'); })
function reOpen() { $('#'+LastModal).modal('show');}
Just use the style class "modal" for your modals, and to call the "reOpen", just have something like:
<span onclick='reOpen();'>Reopen</span>
Thanks #marekful for your suggestion!
Also, if you want to access this (or any other function) by pressing Ctrl+Z, you can add this:
// press Ctrl+Z to restore modal
$(document).keydown(function(evt){
if (evt.keyCode==90 && (evt.ctrlKey)){
evt.preventDefault();
reOpen();
}
});

How to clear a featherlight modal

I am using feather-light modal in my page. on the modal one form is there with certain input fields. Once I fill in the fields and close the modal and when I open it again , it contains the previously filled data. I want to clear the data once it is closed. I am using angular js in my page.
Can anyone tell me how can I clear the feather-light modal using angular js?
Update-
In my code I have to open another modal after closing the first modal. And once second modal closes, if I am opening my first modal, its showing the previously filled data, I want to reset the modal data of first modal.
in my html I am using below code-
<button type="submit" ng-click="anotherModal(myForm)" ng-class="{ 'featherlight-close' : myForm.$valid}">Submit</button>
and in script I am using below code-
$scope.anotherModal= function (myForm) {
if ($scope.myForm.$valid) {
$scope.myForm.$submitted = true;
$.featherlight("#f12","open");
}
}
Can anyone tell me where should I add to reset the first modal?
Updated Plunker-
Please find my plunker here-
https://plnkr.co/edit/cDP1eqtUsKkeMaUiCIoM?p=preview
I am using persist ='shared' in my code because if I remove this then form validation won't work on first modal.
My issue is that when I open my second modal next time,it contains previously filled values and from there when I click on submit button my second modal doesn't show up.
Can anyone help me in solving my issue?
If you are using the persist option, then yeah, the form is persisted, so you'll have to clear it yourself.
If not, then you'll get a new copied form each time. In that case though, you'll have to be careful about how you bind it and avoid using any IDs, since those are supposed to be unique.
As far as I know featherlight is gallery plugin, used for displaying images in a lightbox. Considering this it is not meant to be used like that (even though you can, but it will not behave as you expect here out of the box), so that's why you'll have to cleanup behind you (or more specific your users), and on popup close action, clear all form fields. There are several ways to do that, eg. form reset button (input type="reset"), js callback on close popup or submit event (or in your case using angular js events), etc..
Since you didn't provide any code that's all I can tell you for now..
Also possible duplicate of Resetting form after submit in Angularjs
UPDATE
Not sure what exactly are you trying to achive here, but if you remove (or move inside showAnotherModal function) $.featherlight.defaults.persist=true; line, it works as you described, first popup is cleared when you open it for second time. Here is your snippet updated:
var app = angular.module('myApp', ['ngMessages']);
app.controller('myCtrl', function($scope) {
// $.featherlight.defaults.persist="shared";
$scope.showAnotherModal = function () {
$.featherlight.defaults.persist="shared";
if ($scope.myForm.$valid) {
$scope.myForm.$submitted = true;
$scope.myForm.dirty = false;
$scope.myForm.$setPristine();
$scope.myForm.$setUntouched();
$.featherlight("#fl3",'open');
}
}
});

Dynamics CRM 2016 Online - Refresh record after using dialog

I have a custom button on my ribbon which fires a dialog up. It's part of a workaround Qualification solution I'm putting together.
The creation of an Account/Contact/Opportunity and the choices given work fine, as well as changing the status of the Lead to qualified. The problem is that when the user is done with the Dialog and closes it, they're still looking at the Lead in its original state.
How do I force the form to refresh so that it shows its new state?
I've seen a Javascript solution online (codeplex), Process.js - callDialog() which seems popular but it doesn't want to work as described by the creator on my version of CRM - always get a invalid URL error message & it fires on load of the form as well as when using the custom button.
Has anyone come across a requirement like this and how have you resolved it?
Thanks
Edit: Here is the JS I use on my ribbon button currently. Where do I put my refresh call and what/how do I call the event being used when closing the Dialog.
I tried adding a refresh call at the bottom of the this code but its called whilst opening the Dialog at the start, which isn't much use as the changes I want to see are applied throughout the Dialog itself.
Thanks
Develop1_RibbonCommands_runDialogForm = function(objectTypeCode, dialogId) {
var primaryEntityId = Xrm.Page.data.entity.getId();
var rundialog = Mscrm.CrmUri.create('/cs/dialog/rundialog.aspx');
rundialog.get_query()['DialogId'] = dialogId;
rundialog.get_query()['ObjectId'] = primaryEntityId;
rundialog.get_query()['EntityName'] = objectTypeCode;
var hostWindow = window;
if (typeof(openStdWin) == 'undefined') {
hostWindow = window.parent; // Support for Turbo-forms in CRM2015 Update 1
}
if (typeof(hostWindow.openStdWin) != 'undefined') {
hostWindow.openStdDlgWithCallback(rundialog, hostWindow.buildWinName(null), 615, 480, Xrm.Page.data.refresh(false));
}
}
})();
Check out the Xrm.Page.data (client-side reference), you'll want to call Xrm.Page.data.refresh().
Depending on how you're launching your dialog, and assuming your dialog is a webresource hosted in CRM, the dialog can reach back out to the form it launched from and call refresh, or a callback could potentially be used.
EDIT (based on your posted code): If the 5th parameter of the function openStdDlgWithCallback is the callback for when the dialog closes you'd want to pass the function like Xrm.Page.data.refresh or wrap your call in a function function(){Xrm.Page.data.refresh()}. Currently your code is executing the function right away which is why you're seeing the refresh right away.
Using openStdDlgWithCallback you can subscribe a callback function which runs after the dialog is closed. You can then use Xrm.Page.data.refresh() inside the callback function.

RadScheduler update interval

I'm using RadScheduler for my project. In the scheduler, I need a periodical update, so in my javascript, I set interval for a method that call rebind() on the RadScheduler for every 60 seconds. The problem is that, when my user open the advanced form, the rebind() method makes the form disappear. How can I detect AdvancedForm opening and closing event so that I can stop /restart the timer ?
Thank you in advance.
While there is an event for when the RadScheduler opens its Edit form, called OnClientFormCreated, there is not one for when the edit form closes. There are ways to do this though, but you have do add some additional code.
When you think about it there are several different items that can lead to the form closing - the user can click on the close icon at the top right (or left, depending on your orientation) of the window, they can click cancel, or they can hit save.
Keeping that in mind, we can take a look at this demo, which shows the Advanced Edit Form in action, and also has some JavaScript pre-written for us.
Within the schedulerFormCreated() function we can do the following:
function schedulerFormCreated(scheduler, eventArgs) {
// Create a client-side object only for the advanced templates
var mode = eventArgs.get_mode();
if (mode == Telerik.Web.UI.SchedulerFormMode.AdvancedInsert ||
mode == Telerik.Web.UI.SchedulerFormMode.AdvancedEdit) {
// Initialize the client-side object for the advanced form
var formElement = eventArgs.get_formElement();
var cancelButton = $("[id$='_CancelButton']");
cancelButton.on("click", formClosed);
var templateKey = scheduler.get_id() + "_" + mode;
....
And then we have the formClosed event:
function formClosed(eventArgs) {
}
in formClosed you can just create your logic for resuming the timer, while in schedulerFormCreated you can directly call the function that stops the timer right after that if-statement.
In case you're wondering what we're doing here we're simply grabbing an instance of the jQuery object representing the element with an id that ends with _CancelButton (we're not interested in the beginning part) and then just binding to the click event using the .on() jQuery function.
To get an instance of the save button you just have to use _UpdateButton, and for the close icon it is _AdvancedEditCloseButton. Keep in mind that any element that ends with these substrings will be selected, so if you want to be more specific I recommend inspecting the elements of your advanced form using FireBug or the Chrome Dev tools to get their ID and plug that into the selector above.
This should allow you to get the functionality you're looking for.

Categories