TempData moving from view to controler - asp.net-mvc-2

I am attempting to call a controller via an actionLink() in a view. This controller get's data from a TempData repository. However, it seems that no matter what I do, if I set the TempData repository in the view, it won't go over to the controller? Should I use ViewData instead? What is your recommendation for a system such as that?
Thanks

TempData, nor ViewData is supposed to be set in a view. A view is supposed to consume data that has been stored in those structures inside your controller actions (well, actually it isn't, a view is supposed to consume a view model but that's another topic).
TempData could be used when you want to persist information between two redirects. It should be set inside a controller action which redirects to another controller action that will read the data:
public ActionResult Foo()
{
SomeModel model = ...
TempData["foo"] = model;
return RedirectToAction("Bar");
}
public ActionResult Bar()
{
var model = TempData["foo"] as SomeModel;
...
}
So a controller action should get data from the TempData structure only if this action has been invoked after a redirect from another action that set the data. Such controller action should never be invoked from a view because if you have a view this means that this view was rendered from a controller action that presumably set the data into TempData but there is always a risk (if the view performs in between a request to the server - AJAX or something), the TempData will be lost.
For your case, when a view needs to invoke the server there are basically 3 techniques:
Use an HTML <form> with input fields that will send the data to the server
Use an anchor and pass data as query string parameters to the controller
Use javascript and send an AJAX request or a redirect to the server

You should set the TempData value beforehand, in the controller that renders your view. The value will then get picked up by the controller action that renders your second (ActionLink) view.

Related

How to send Data to a controller while navigating to a view

I have this route
Get.toNamed('/community/discussion/${controller.community.topicId}}');
While navigating to the view, I want to pass the route parameter topicId to the view's controller so that it uses as document ID and load the content which will be stream to the view.
How can I send this parameter to the controller before the view's content is streamed?
I guess you're not using Get.toNamed the way it is supposed to.
Function toNamed takes a dynamic parameter arguments that you can use for your purpose.
In your source screen:
Get.toNamed<void>("/community/discussion/",
arguments: {"topicId": controller.community.topicId});
In your destination screen:
var topicId = Get.parameters['topicId'];
Then you can easily set the topic id into your controller:
controller.topicId = topicId;
class YourController extends GetxController {
int? topicId;
}
If what you're trying to pass already lives in a GetX class, which it appears that it does, then you don't need to pass it at all. Anything that lives in a GetX class is already accessible from anywhere with Get.find...
Just access it on the next page with
Get.find<WhateverThisClassIsCalled>().community.topicId

Accessing function and model in one controller from another view's controller UI5

I have 2 view A and B with their respective controllers and models defined inside. Due to some reason I have to move 2 elements from A to B view. One of the element is a button link with a press event. I moved the elements to another view but when I click on the link, it does not trigger press. Which I understand is because B 's controller does not have function for that. If I write the same function in B's controller I get an error saying the model's setProperty could not be set as not found. Because that model is in scope in A's controller only. How do I access it?
Press event of link:
pressEvent: function(oEvent) {
this.getModel("stock").setProperty("/Links/Visible", true);
var stockroomsarr = this.getModel("stockRms").getProperty("/Stockrooms");
if (stockrooms !== null && stockrooms.length > 0) {
this.getModel("stock").setProperty("/Text/Visible", false);
}
this.getModel("stock").refresh(false);
},
Regarding your Model: I strongly advice not to have own models for each controllers. Instead you should define and set them in the init of your component.js. They then are accessable in the view controller by calling
this.getOwnerComponent().getModel("urModel")
Another variant would be to create a baseController. In that you can define functions which are to be used by multiple controllers as well as your models. All other controllers extend that baseController, so the models are available in all of them via:
this.getView().getModel("urModel")
Regarding the function you may use the Event Bus. In short it allows you to create events that are triggered in controller A and are listned to in controller B. Read up here for detailed information on how to use it:
https://blogs.sap.com/2015/10/25/openui5-sapui5-communication-between-controllers-using-publish-and-subscribe-from-eventbus/

GWT Activities: Widget added to view again when using browser back button

The way I understand it, if I want to add widgets dynamically to a view created with UIBinder, I would do that in the start method of the activity that is the presenter for that view.
Here's my code:
#Override
public void start(AcceptsOneWidget panel, EventBus eventBus) {
view = clientFactory.getDashboardView();
view.setPresenter(this);
ArrayList<Department> deps = ModelFactory.getDepartments();
view.passData(deps); // Correct?
panel.setWidget(view.asWidget());
}
public void passData(ArrayList<Department> departments) {
TextCell text = new TextCell();
CellList<String> cellList = new CellList<String>(text);
String[] departmentNames = new String[departments.size()];
for (int i = 0; i < departments.size(); i++) {
departmentNames[i] = departments.get(i).getName();
}
cellList.setRowData(Arrays.asList(departmentNames));
departmentsDiv.add(cellList);
}
It works. However, when using the back button to navigate to the previous place and back, the widget is added again.
How do I handle this correctly?
You have two options:
If you don't want to refresh the data on each visit to this view, you need to add a flag to the view to tell if the data has been already populated. Then, when this view is visited again, your activity should call view.passData(deps); only if the flag is set to false. After the data is loaded, set the flag to true.
If you do want to refresh the data on each visit, call departmentsDiv.clear() before adding a new CellList.
NB: A better approach is to create your CellList once, when the view is displayed for the first time, and then only call setRowData when the new data is available.
You are creating View object by using Factory method. You should consider creating views during application load using, for instance: GIN and marking them as Singletons. The proper way is to pass them as start() method parameters and just set presenter reference on them.
General idea is to make Views singletons. Activities should be created while throwing GWT place (stateless) and just using singleton Views, so you can keep your view input data.
Read tutorial here on using MVP / GIN pattern: http://blog.hivedevelopment.co.uk/2009/08/google-web-toolkit-gwt-mvp-example.html

How to retrieve view from controller of another view?

I am just wondering how can I get one of the UI5 views in an application.
I know there is a method:
sap.ui.jsview(); // in case the view is written in JavaScript
But the problem with this method is: if you assign ID for any of the controls and you have already inflated this view, you get an error.
So I want to know how to check if the view already exists and then if yes return that existing view, otherwise create the view with the corresponding API such as the above one.
I also know in the control for view I can go
this.getView();
But as I said, how to get this view from another view?
I am not quite understanding your question
With managed object id's are unique, so if you try and create the same view twice you will get an error.
when you create your view the easiest way to access it is via an Id
sap.ui.jsview("view1",'testapp.view.view1');
sap.ui.getCore().byId('view1');
NB. views should not talk to anyone other than their controller A terrific Model View Controller (MVC) diagram
sap.ui.getCore().byId(<id_of_the_view>)
Where <id_of_the_view> can be obtained in the following way:
suppose that the corresponding controller of <id_of_the_view> is "controllerA.js",
then you can console.log, inside controllerA.js,
console.log(this.getView())
This will print you an object which contains the id of such view. This will be <id_of_the_view>
I think here is one solution.
Make a global variable;
Use it to create element.
In First View:
var mytextField ;(use it as global)
mytextField = new sap.ui.commons.TextField('textfieldId');
In Second View:
var myValue = mytextField .getValue();
~Mansi Rao

Can i have Multiple ViewModels being held in a ViewModel?

I was wondering what your thoughts are on having a ViewModel containing a collection of other ViewModels.
For example if i have a stock price screen. In the MainView i want to be able to selct a stock ticker. When i press the ADD button on the MainView it should display a new stock price in the MainView.
My question is about how the add button should work?
Which of the two options should the Add button on the MainView do:
1) Pass the stock ticker (MSFT) to StockPriceService. The StockPriceService will retrive a StockPrice object. I can then pass the StockPrice object into a StockPriceViewModel. The MainViewModel will contain a collection of StockPriceViewModel.
2) pass the stock ticker(MSFT) into the StockPriceViewModel. The StockPriceViewModel will be implemented to call the StockPriceService and retrive the StockPrice object. The the StockPrice object will then be wrapped in the StockPriceViewModel.
Thanks,
CA
If the Add button is part of the MainView then it's events really should be handled by the MainViewModel and access to data for the StockPriceViewModel and thus StockPrice object, by the StockPrice related code.
The way to look at this is that you should still be able to display a StockPriceViewModel with populated data without recourse to any code in any other ViewModels, but in this case it is the MainViewModel that triggers the creation/instantiation of a new StockPriceViewModel etc.
So that would mean go with mostly method 2, say passing an initialisation value to the StockPriceViewModel constructor.