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.
Related
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
In a (webforms) page I have a button that opens a jqueryui dialogue which is loaded dynamically.
The problem is that I want this dialogue to be master of its own knockout view model but the view model is already set in the main page.
I suppose it is not possible to add new properties to the view model after ko.applyBindings is called.
Instead I should be looking into another design. But which?
Applying bindings to different parts of the DOM would require me to some big redesigns I hope to avoid right now.
Having all the dialoge bindings as a list of key-values is possible but not very elegant IMHO. The main page would then only have to add a vm.dialogueKeyvalueCollection.
My present, possible, solution is to have the main form add the dialogue's properties vm.dialogue.userName() vm.dialogue.searchResult() but then my html controls won't bind as they are created after applyBindings is called. The present solution for this is to call ApplyBindings again like so: ko.applyBindings(vm, $('#dialog-form')[0]); for the added HTML. I was in the belief (and still somewhat am) that to call applyBindings for different DOM elements one must not be nested inside another. Binding to dynamic HTML is commented here and jsfiddled here.
?
I do a lot of composition with nested view models, often for the purpose of creating dialogues modals. See here for a full-fledged answer.
It might be simpler to try and get away with just using the with binding, though. You could create a dialogueViewmodel observable property on your viewmodel.
Just fill it with one or more observable keys when you're ready to show the dialogue, such as
this.dialogueViewmodel({
markup: ko.observable("<h1>Kittens!</h1>")
});
and wrap it in a with binding:
<!-- ko with: dialogueViewmodel -->
<div id="dialog" title="Basic dialog" data-bind="html: markup">
</div>
<!-- /ko -->
As long as dialogueViewmodel is null, nothing gets bound and rendered. This only happens when you add your dialogue data - no need to fiddle with applyBindings again.
You will probably have to write your own binding to interface with jQueryUI.dialogue, though.
Third option: I have written a modal library that comes with a Knockout binding out of the box. Here's a JSfiddle demo. If you're not set on jQueryUI, that might be an alternative; while the documentation is not perfect, I'd be happy to help you any way I can and fix the docs along the way.
Can you ko.applyBindingsToNode function to bind the appended html.
ko.applyBindingsToNode(appendedelement,{ binding options})
Hope this will help you.
I want to disable all the functionalities provided by Angularjs, but only after the pages and all components have been loaded fully.For example "ng-click" should not work any more.
I tried to set the "ng-click" attr to null but, it still works when clicked.
Thank you
You can destroy angular app $scope that means it will disable only two way binding of scope variables using $scope.$destroy() method nothing more than that(If you want to disable two way binding on start up load then you need call $destroy() in $timeout).
But the event listener won't get disabled from angular app which are register while angular app is initialized on page. You can only achieve this by maintaining any flag (this is hacky way).
Here is Fiddle which demonstrate what i want to say.
Thanks.
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.