Angular modals (ui-router) and general modal architecture concepts - angularjs

I am working on a fairly complex AngularJS web application and keep failing to implement a working modal / routing mechanism which meet my requirements.
Situation
My application has (simplified) the following entities:
Customers (has 0 or more Contacts)
Orders (has exactly 1 Customer)
Contacts (belong to exactly 1 Customer)
During the creating of a new order an existing customer can be selected, or a new customer can be created. In the creation process of the customer, optionally a new contact can be created.
UI / UX solutions
I've looked at several ways to correctly represent this functionality in a "non-cluttering" and mobile friendly way. First I tried to stay away from modals or popups completely and tried to create several Angular directives to be shown dynamically in the page, but this soon got way too complex. The creation of a new customer exists of multiple UI-states and some substates (tabs) and has fairly complex logic in it.
Then I looked at using separate browser tabs and communicate between them using localStorage. However this approach seemed fragile and also not really common for a user. Besides, the user should continue working in the new tab until finished, and only then be able to return to the previous tab. This is not possible using separate browser tabs.
I've looked at Javascript browser popups, but I don't like that direction either.
From a users point of view, I think the best way was to use a Modal dialog to follow the UI flow:
UI flow
+----------+ +------------+ +-----------+
|New Order | - Opens modal -> |New Customer| - Opens modal -> |New Contact|
+----------+ +------------+ +-----------+
^ | ^ |
| OK | OK
| Closes modal and | | Closes modal and |
| selects new customer | | selects new contact |
+----<-----<-------<-----<---+ +----<-----<-------<-----<----+
Note: the New Customer and New Contact states are also states on itself which can be opened in a regular window.
I have created Angular-UI-Router routes as:
New Order: app.orders.new
New Customer: app.customers.new
New Contact: app.contacts.new
Development
To support the multiple modal architecture I've tried several things:
Using Angular UI Bootstrap Modal
Using the UI-Router-Extras way using own built Modal windows
Some important aspects to keep in mind:
I do not need direct URL's to point directly to a modal window. The URL can stay in the "New Customer"-state.
The behavior should be Modal, so not able to work on the parent window.
It should be able to open and show multiple states after each other (for instance a wizard in one Modal)
Multiple modals that are opened in a certain order should be closed the same order. (Last in, First out)
1. Using Angular UI Bootstrap Modal
This way seemed promising. I've created a separate routing which use the some controllers and views of the regular routes:
Modal.Customers.New
Modal.Contacts.New
But unfortunately I struggle to open more modals inside the modal and keep state of the previous modal. I've used UI-Router-Extras Sticky States to keep the background state. However as UI-Router-Extras states, Sticky States only works when every state has it's own ui-view. A ui-view should be declared beforehand. This is not possible, because in theory a user can open an unlimited amount of nested modals in my application.
2. Using the UI-Router-Extras way using own built Modal windows
I've tried creating a simple modal in stead of the Angular UI Modal using the simple Modal example of UI-Router-Extras as in: http://plnkr.co/edit/qgt0RkEnXDPDTdMJPIfy?p=info
But unfortunately I have the same problem as with option 1. The problem is the states and routing gets too complex when modals are nested.
Solution
I am really struggling about what is the best approach now. I am thinking about showing a Modal overlay window with an iframe in it which open a seperate UI-Router route like: Modal.Customers.New, which shows only the contents of the application (not the menu bars, etc).
When using iframes I am able to keep the separate route and states info available on the parent window and the iframe. I need to perform some custom javascript to support scaling the iframes to the right format, but that is acceptable.
But it still feels like a "hacked" solution.
I would love to hear your solutions and insights.

Eventually I went for a combination of using an iframe with Angular UI Modals. This approach gave me complete flexibility in using complicated routes in my App and the Modal screens of Angular UI automatically resize the iframe on different screen resolutions.
I have created routes for all states used in Modals with the prefix: modal. in stead of app.
This way I could only use the "content" subview of the page to show inside the Modal and still have full re-usability of the original controllers and views.
The only tricky bit was when multiple nested Modals are opened. There I had to check if I was in a Modal or in a regular state. This was pretty easy using the state name:
IsModal() {
return this.$state.current.name.indexOf("modal") == 0;
}
On the root frame (the non-modal view) I collected all opened Angular UI Modals in an array and checked on opening a new modal if the Modal was at the root of the views (non-modal). If not, I traversed up the iframe to the parent scope using:
var parentScopeModalService = (<any>parent).angular.element(window.frameElement).scope().MyModalService;
This actually worked pretty nice because all iframes are on the same domain.

Related

Can a UI be kept rendered even if it does not match its react-router route?

would anybody here know if it's possible to do something like what happens in this screen recording? https://www.dropbox.com/s/snhhbeq8knk5dyc/modal-window-routing.mp4?dl=0
It's about routing a modal window, while keeping the UI underneath intact. Normally I'd say that to achieve this in React router the URL would need to encode both what's behind, and the modal. Maybe with some nesting scheme (e.g. /mainview/settings/general). But Outlook web manages to do so while not reflecting in the URL the view that was present when the modal was fired.
Note in the recording how the URL for the settings modal is the same, regardless of whether you open it from the Drafts or the Sent Items or wherever. However, the view from which you opened is kept rendered, and it's where you go back to when you close the modal.
according to the react-router-dom documentation, the following link lays out the proper way to go about achieving your desired result https://reactrouter.com/web/example/modal-gallery

Opening a pop up from angularjs partial page

I have an AngualarJS app that has an index page and some partial pages, displayed in ui-view. The app is using ui-routing. I have a button on the header (located on the index page) and on click of that button I want a small pop up open - a page displaying some data from the database, based on currently logged in user. I am trying to decide between opening a windows with window.open and sizing it to about 400x400 but that seems very un-elegant plus I see some issues with opening it. Another option I am entertaining is bootstrap ui modal but that would involve including bootstrap in my project on top of all the angular and routing includes.
Not sure if there is a better way to go, would appreciate any leads.
If you don't want to include bootstrap in your project You may use this one
--> http://www.dwmkerr.com/the-only-angularjs-modal-service-youll-ever-need/

Generate icons, and its properties, dynamically using controllers

I'm using angularJs 1.3 with Angular Material Design 0.8.3 and I have a page that has a toolbar on the top <md-toolbar class="md-whiteframe-glow-z2 md-default-theme"> where I'm trying to put some icons dynamically. The page has some crud's and each crud has it own controller. The case is, each crud must have it specific icons at the toolbar, I'm trying to specify it through the controllers but I have no idea how can I write this cuz each icon should have it owns properties (the href link, the action function etc). Someone know if its possible to apply this idea (control the icons that will appears in the screen per crud via controllers)?

Opening a Browser window popup in ExtJS 5 MVC application

I am working on an application in which we open all the views in a tabPanel, it was pretty simple to do that.
Now we got a new requirement where we have to open the view in Browser popup window so that it can be dragged to a secondary monitor. Ext.Window will not work.
we have a single page application and not sure how i can open a view in separate browser window.
i have tried the following, but then no JS events works on the new window:
var OpenWindow = window.open('', windowName, 'width=330,height=200,resizable=0');
OpenWindow.document.body.appendChild(divObj);//divObj is a div object in which i rendered the extjs view.
it open the popup but non of the style or js is working.
please help or point some example where it is accomplished.
Thanks in advance.
When opening a new window it doesn't have any information about ExtJS at all. you will need to include extjs into the new windows html. The best way to do this is to create a new popoup index file or page to be called. so say you are using routers properly in extjs say you have a site called http://testsite.com
Then you can in your window being opened create the elements in your current application to load when calling testsite.com/#popup then you just place it into your window.open. If you are managing your calls with something like PHP and using a framework for routing you can set it up the same way and have your javascript and extjs to be called from it as well.
var OpenWindow = window.open('http://testsite.com/#popup', windowName, 'width=330,height=200,resizable=0');
Reccomend creating a router like this: Extjs Routing Guide and from there have the component brought into focus on the page and placed that url into your popup if no backend system is used. Creating a new route in a backend link would be the best way to go, but you will still need to call your extjs applications components into your new page as well.

Angular.js + Bootstrap: how to show all views on vertical scroll?

I'm building my first Angular.js + Bootstrap web site.
As far as user interface is concerned, I use a classical top navbar approach, with 7/8 items in navbar linking to the relative views. This is a first version of the site. When you click on "weather", you go to the weather page. When You click on "services", you go to the services page. That's ok.
But, I would like, for a better mobile user experience, when scrolling down, all views to be shown, in sequence... This is an example of what I mean, to be clearer...
Is it possible, preserving the angular.js "routing" logic?
UPDATE: I did change the page contents in the first link, adding two links in navbar, because of Ronni Skansing comment...
UPDATE2: I try to better reformulate the question:
Is it possible, with angular.js (+bootstrap), to design an UI with all views reachable without any click, but continuously, vertical scrolling the page, the way a typical mobile web app user is used to?
I don't think you can really have a single page unless you design your website to be a single page.
Anyway, I found a solution which is very similar to what you would like: simply add a transition on ng-view change. The user won't be able to scroll, it will still have to click on the navbar items. But the sensation will be similar to scrolling. See here the example. (remember to choose the slidedown effect)

Resources