In my React app, I want to create a popup window that renders a table with some data. However, I want to make it render in a separate browser window instance as opposed to a modal that is attached to the app's DOM. Most of my research has led me to third party component libraries that just render an in-DOM modal just in different ways. What is the best way to create my desired effect, where clicking the "Open" button creates a new browser window instance that renders the table component?
Thanks
hmm.. maybe try the window.open() syntax
https://developer.mozilla.org/en-US/docs/Web/API/Window/open
Related
I want to create a generic component that should detect required component View outside click (hide the View/dropdown, etc. when pressed outside). Basically it's for the Autocomplete Search Dropdown but I guess such functionality could be used in the future for other things.
The content should be dynamic and could be passed from any level of the app because such functionality is a common UX thing.
It shouldn't be modal that always render content at the screen center because a dropdown should be opened below its trigger, etc. So it should respect the initial component position. (In think to use onLayout/measure API of the initial position when passing the content into the Backdrop)
I researched a lot of resources and found that the one possible way is:
Create a TouchableWithoutFeedback layer (Backdrop) at the top level of the app.
make it fullscreen with/height
When dropdown is shown: render the Backdrop and onPress on it - close the dropdown & backdrop.
The main question is: How to pass a generic content into this Layer and save its relationship with the parent/props, re-render when needed, etc.?
Please, keep in mind, that the component which should pass content for this layer could be deep inside the app.
I guess it could be done via Context API, etc. but I'm not sure if it's the best possible way.
P.S. in the case of web it's a trivial task: create a fullscreen layer -> use a portal -> move content at the top level of the app -> render it at the required X\Y position and listen for the outside press.
I didn't expect that such functionality will be a problem in the case of RN.
Thanks for any help.
I am using Angular's DomPortalHost to open a child component in a new browser window. It works for the most part.
Here is a working prototype of opening a child component in a new browser window:
https://stackblitz.com/edit/portalfun
I am able to pass data to and from child component - works great right?
Well.. when I have let's say, a map in the new browser window some of the map events seem to think the map exists in the original browser window. See:
https://www.youtube.com/watch?v=0387htqmXZw
Hilarity ensues:
I am able to click once in the new window to begin a selection (circle, etc) but not a second time. Using the view +/- controls seems to work fine. However, the map navigation/scrolling and the selection events think they are controlled from the original window.
The endgame for this little innovation project was to pass whatever data was selected in the map (syncing the grid you see in the background and the map). This works fine when I don't use DomPortalHost (that area below the grid is where the map was originally and it functions correctly).
I think that because *cdkPortal (see the stackblitz) is technically inside the original browser window:
<window *ngIf="showPortal" [dataFromParent]="dataToPass" (dataToParent)="this.onClosed($event)">
</window>
selector: 'window'...
<ng-container *cdkPortal>
<h1>Child component window</h1>
<div>{{dataFromParent}}</div>
<a class="btn-3" (click)="emitClose()">Close Window</a>
You can also close the parent window, or navigate to a different route. It will close the child window component.
</ng-container>
It's as if the map think's its been rendered in the original window, but is actually rendered in the new window.
The closest.. discovery that i've had was that some of the event handling has a [[Scope]] property set to the original window - not the new on. However I don't see how to overwrite this property.
If anyone has any ideas, resources, or a better approach please feel free to let me know. This is part of an innovation sprint, but it'd be cool to get it working as i'm sure it has a lot of use cases for others out there.
Imagine opening child components and passing data back and forth in new windows.. and not having to run a second cloned app or deal with the overheard of state management :)
I'm new to angular and i'm using bootstrap for modal window. I have certain queries on how to implement it properly.
1) Should a Modal Window be a route?
In the example the window is triggered by a javascript rather than a route on an anchor
<button class="btn" ng-click="open()">Open me!</button>
http://plnkr.co/edit/IDOoeYQticjRZA4uMGJx?p=preview
Is the above approach correct or should there be a route to trigger? If yes then how can I do it, example would be much appreciated.
2) If javascript is used to trigger the window how can I do routing inside the modal window?
PS : I did watch http://egghead.io/lessons/angularjs-introduction-ui-router video on the ui-router for understanding but not sure how it can be implemented when javascript is used.
I did try triggering the modal from a link but it does not open up the second time.
http://plnkr.co/edit/b2Hy7VIjgBwI8HpI90KN?p=preview
Example would be really helpful.
I use Foundation's reveal with AngularJS, which is similar to Bootstap's modal. The modal itself isn't a separate route, as like you, I trigger it via Javascript from the controller. I think this is fine though, as it's usually related to the scope of that controller, e.g. creating / editing records for the list, etc.
The content of the modal/reveal is a separate template though, so is only loaded and cached as needed, and the modal has its own controller. My 'parent' controller can inject values into the reveal controller via the provider I use, which is presumably similar to how the Bootstrap modal provider works.
So, in my opinion I think it's perfectly valid for the modal to not have its own route, but perhaps someone out there has implemented things differently.
Update: I also think that routing (with the ng-view directive) is more about single page applications. As the ng-view element is constant, I don't quite see how that would work with modals, as you'd presumably lose the context of the view from which it is loaded.
I have been working on this task off and on for awhile trying to find an optimal solution (other than telling users to disable popup blocking) and am stumped.
Essentially how it works is this (I omit code because there is a lot of it and propriety info):
I have an angular app implemented in an angular and utilizes fullcalendar.js who's content I want to print. Inside my angular controller I have the jQuery that manages the calendar itself (don't hit my fingers with a ruler please :) )
I want a specific set of styles when I want to print the calendar, so I have a directive that prepares all the content to be ported, and then use a uniform angular factory that is used for all printing activities. This uniform factory opens a new window that contains all the new styles I want and, via a callback, "cleans up" the HTML, which in my case I use for porting the HTML content of the calendar over to the new window.
So the flow basically is this: User clicks print button -> click event in calendar print directive is invoked, the directive calls the factory. -> Factory opens a new window and ports the content via the callback from the directive and then calls JavaScript's print() to print the window.
The problem I am encountering is this:
The print works fine on PC and Mac, but on iOS safari, the window does not pop up. I found that the issue was because iOS Safari requires all new window popups to be inside a click event.
To get around this, I thought I would add some modification to the uniform factory to suit my case: I would open a new window in the directive's click event, then pass a reference of that window into the factory, which can then use the reference to add the html content to its body. This introduced another issue with iOS Safari in that it stalls javascript execution of parent windows if a child window is open, so once the new window is open, the generation of the HTML and the calling of the factory is stalled until the user switches back to the parent tab. This is the point where I got stumped. Any suggested way to get around these issues? Or would I be stuck telling the user to disable popup blocking?
once the new window is open, the generation of the HTML and the
calling of the factory is stalled...
Can you change so the generation of HTML and factory call is made before opening the new window? Otherwise it sounds like you need to avoid the popup.
If you want to display another view in the same window, use ngInclude.
You can choose to switch the path of the ngInclude to swap the HTML or combine with ngShow to show and hide the correct parts when the user clicks.
It sounds like you use a factory as a parent scope and if so it should be converted to a controller that acts as a global scope above the different views.
If this is on the right track I could make a plunkr out of it.
Also, check out fullcalendar-ui for a premade directive if you want to go towards best practice.
Good luck!
After ~3 times coming and going from this over the course of a month, I finally figured it out.
Inside my directive that prepares the content to be printed, I generate a new calendar, then call the rest of the code (including the factory that opens a new window) inside a document.ready. Having the code inside the ready check seems to cause iOS Safari to think it is no longer directly inside a click event, so it would sometimes block the new window popup. Removing the document.ready check seems to have made it work, and has no ill effect on the other browsers.
I decided to create a function inside the directive for the factory call and call inside a document.ready if not iOS, otherwise just call it, to preserve functionality for desktop browsers.
The Filepicker.io modal widget (specifically the "IMAGE_SEARCH" service) appends to the window.history in the DOM after a search is made. This creates an issue working with Backbone.js when attempting to go back a previous page.
What causes this, and is there any way to prevent it?
[edit] Incorrectly referenced "IMAGE_SEARCH"
What causes this:
Navigation around the modal manipulates window.location.hash for compatibility with the window view and a number of other conveniences. Why these changes are affecting the window.history outside the iframe sandbox, I'm not sure.
How to prevent it:
I'm looking into whether we are leaking state somehow, but one easy way to prevent it is to use the {container: 'window'} option for filepicker.pick(), so that the dialog is created in a separate window.