I'm using Vaadin 8 in a Spring Boot application and have a view scoped View.
I'm using view scope because I want to have a new instance each time I navigate to the view, and more importantly I don't want the view (and its data) to remain in memory when the user has navigated away from the view.
However, I would like to be able to navigate to this view from within the view itself, with different parameters. In that case I don't want the view instance to be recreated (and its data to be reloaded). Is there a way to do that? Maybe with a custom Spring scope?
Related
Let's use an example of a blog built by Marionett. The blog post is a sub app and hook the route post/:id. It also has a controller, inherited from Marionette.Controller. Quite normal.
Each hit to post/:id will create a new controller instance, managing the related model and views. The controller instance will trigger App.vents but won't listen on App.vents.
My question is, since there will be so many instances of the controller created when an user navigates around, should I concern the close of the instances when there are a close() method available in controller? Will there be memory leak if not closing them?
Thanks.
There could be a memory leak depending on what's inside your controllers. Also if you're controller is using listenTo to watch events on other models/objects you could get a build up of zombie events. Without seeing your code it would be hard to say for sure.
In general, I think why not just close the controllers? The way I do this (from BackboneRails tutorials) is to have the first view controller the renders (typically a layout) as the main view and then bind to the view's close event--when the view closes the controller will call close on itself. You can build this into your base controller so it happens automatically. This has worked pretty well for me...
I am adding some functionality to an existing Microsoft MVC 3 application. I cannot change the existing structure of the app itself while I do need to add some new functionality to the page. I have angular running in a div (hidden on load via jquery dialog). The MVC app has several tabs on the page. Each time a tab is chosen, the a partial cshtml (razor) loads. Along with that partial, my angular template is included. The partial references a js file that contains the angular controller. When it is first loaded and the user opens the tab and open the jquery dialog containing angular, everything works fine. I started to notice some funny behavior after the changes are saved. I noticed the same irregular behavior if I closed the dialog containing the angular template, switched to another tab, then switched back to the tab containing the angular template. Here's what is happening:
The partial being loaded by MVC reloads the angular template which initiates the angularjs controller method in the referenced js file
A new $scope is being generated each time this occurs.
Each time a controller method is invoked (via ng-click event tied to a button on the template) teh method will execute n number of times with n being the number of times the partial has been loaded since the last full page refresh.
I proved this method by logging the $scope object to the window in the start of the controller method
window['scope_' + new Date().getTime().toString()] = $scope;
After each partial page load, a new $scope object is logged to the window. Pressing a button on the template invoked a certain method tied to the ng-click event. This event fires multiple times. But calling the method manually in the console using the oldest recorded scope object in the window
scope_1378413848781.$apply(scope_1378413848781.getSomeData())
it works as intended. So, my question is, how do I prevent the controller from adding a new scope every time the MVC framework reloads the partial?
Here are some of the things I've tried that didn't work:
Adding a global flag and exiting the controller method if it was set
moving the controller reference to the _layout.cshtml file
destroying the scope when the dialog containing the template is closed
One final note, I am not using the angular route provider which I know can cause the controller to execute twice when used in conjunction with .
It appears that Angularjs was not meant to be used in this fashion. Per the angular docs:
You can use Angular to develop both single-page and round-trip apps, but Angular is designed primarily for developing single-page apps...You normally wouldn't want to load Angular with every page change, as would be the case with using Angular in a round-trip app.
To resolve the issue, I moved the angular template as well as the reference to the controller and angular.min.js to the shared _Layout.cshtml file. This partial file loads first and is only reloaded when the entire page is refreshed. Adding angular references and loading controllers in js files referenced in asp.net mvc 3 partials will cause scope replication that can be difficult to detect.
I'm not sure if the question title really explains what I want to do, however I will explain below:
I am using the Visual Studio MVC project template and I have changed some of the tabs to map to different actions from different controllers. However I want to make one of the tabs to open a view that will again have links for different administration actions.
The problem I have is that I am unsure where to place this view as it doesn't really belong to an admin controller as each tab on this view will link to a list view in another controller. In effect it is a sub _Layout view, as it doesn't have anything to do with a controller.
I hope I have made myself clear enough!
You can place this view in the Shared folder since it will be used by multiple controllers. Or, you could place it somewhere else and reference it by using the full path to this View/Partial View
In a Controller
public ActionResult SomeAction(){
return View("~/Path/To/View/ViewName.cshtml");
}
In a View (Razor)
#Html.RenderPartial("~/Path/To/View/ViewName.cshtml");
With that said, the Shared folder makes the most sense since it will be shared across multiple controllers.
I'm asking this because I really don't know where I should handle events of my dynamically created window.
When someone clicks on a desktop icon, the window (if it doesn't exist) will be dynamically created. Should I create a controller when creating the window and hook to it? If yes, how?
Here you can read different approaches I've thought about:
Create a controller that will instanciate the Window (as its view), I will handle everything there
Create the window only and hook everything in my taskbar controller (which is where the window is created). In this case, the Taskbar controller will become very big.
Pre-create all window controllers and eventually windows too and hide them (when page is ready). Then just show/hide them, so I will have "static" references to all controllers with getController in Application
Which approach should I use?
Edit 1:
I'm trying to dynamically instanciate (and reference it through another controller) a controller. I'm having hard time expecially in referencing it. Any suggestion on how it should be done?
I found Ext's MVC unusable with desktop demo as it's possible to have multiple windows (views) of the same type tied to a single controller. Each window has it's own state and it's hard to differentiate between the views in the controller.
I solved the problem by myself: I preinstanciate the controller as I do with all controllers, by inserting them in Application controllers array. After this, I instanciate the view on that controller when a method is called, then I simply use refs to access this view.
The method is quite clean and using refs feel so good. Obviusly the controller has a method hasWindow which checks if the controller view has been created already.
I was making some test with my JSF-app and when I tried it in the same web-browser on different tabs, in all tabs the last session was present.
How can I prevent this?
That isn't possible without hacking/changing the browser. But this really shouldn't matter. If that causes unintuitive behaviour in your JSF application (e.g. data of one tab is been redisplayed in another tab), then you were apparently storing view scoped data in session scoped beans. You should store view scoped data in view scoped beans instead.
Or if it is purely intended for testing purposes (i.e. you just wanted to test physically separate user sessions), then you should use physically separate browsers. E.g. one Firefox and one Chrome.
Or if you absolutely need to have "one user session per tab/window", then store the logged-in user in a view scoped bean instead of a session scoped bean and exclusively use ajax postbacks to navigate through pages (SPA - Single Page Application).
See also:
How to choose the right bean scope?
How do servlets work? Instantiation, sessions, shared variables and multithreading
How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)