I have an action that populates the result from the DB. Right now, I see a way of doing it and that is to make the Action ServletRequestAware, set the populated list as a request attribute and show it in jsp.
Since a lot of improvements have been introduced into struts2, is there any other way of doing that? The first thing that comes to my mind is to use displayTag and change the return type of Action to a List, but that does not seem to work.
Thanks for any replies in advance.
You question is unclear, you should read some book about Struts2 to get the general idea.
No need to make the Action ServletRequestAware. The mapping from http parameters to actions fields is automatically done via the Param interceptor (already set in the default configuration). And one of the points of Struts2 is decoupling the action from the http protocol, you should not (typically) do anything related to http in your action.
Tipically, in your action execute() method (or whatever) you'll get the data to display from the DB and set it as one property of your action, so that is accesable from some getter.
Then, in your view page (JSP or whatever) you'll display it. You can use displayTag, but first you'll prefer to display it "manually", to understand what's involved. See for example here http://www.roseindia.net/struts/struts2/struts2controltags/iterator-tag.shtml
For manually displaying a table, also see this example http://www.vaannila.com/struts-2/struts-2-example/struts-2-crud-example-1.html , search for the <table class="userTable> tag.
Related
I'm playing around with ASP.NET MVC 4, but I have some problems with understanding. For better explanation I will use a simple "synthetic" situation.
Let's say I have model Person with 2 properties:
string Name
PersonType Type (e.g. Student, Employee, Military...)
Let's say in my controller I have private property Person. I can initialize this object in Index method, pass into View and build html page. Ok.
Now when user updates one of fields of person instance at the client side (he can input a new person name or select new person type using dropdown list), I want to update my model immediately. So, my general question is How can I achieve it?
Obvious solution for me: I can send an ajax request to controller from JS with new data. I thought that I can call controller's method UpdateName(string name) and update manually property Name with new data. BUT my person instance is NULL inside of this method! My second question is Why I can't access to initilized model object from other method? I think it's all about my bad understanding of client server interaction.
The final case of my situation: when user click's on the button "Save" I want to save created person into file on the server side, but I don't want to use any forms and receive all needed data just after clicking this button (because in my real task I can't use forms and also I can't receive all needed fields from html page after button clicking).
I have found the dirty solution. In JS I created another class Person with same properties. Now I can update instance of this class when I want and pass json data to server for saving it.
Is there any better solutions?
Its not that dirty to have javascript objects to represent your model. In fact thats how I do it. I use KnockoutJS to give me a client side model - which is essentially the MVVM pattern.
You are trying to use the MVC model in a way which you can't. However, the Knockout model you can use how you wish. You basically have a javascript representation of your server side model and once you are done with it you send it to the server.
In order for your server side methods to pick up your client side model you simply have to ensure the post request contains the data and as long as properties names are the same in the parameters of the method they will match themselves.
Why I can't access to initilized model object from other method?
Because it's not initialized anymore. Don't use the controller class to store persistent data across requests. The controller object is disposed after a request completes and then re-initialized on a new request. So anything that one action methods saves at the class level is gone when you get to another action method. Each request from the client to the server should be considered a fully isolated event, independent of any previous requests.
When you want to save your model, what you would do in that action is re-fetch it from the database, apply the changes, and save it back to the database.
but I don't want to use any forms
I'm not really sure what you mean here. Do you mean you want to use AJAX instead of POSTing the page directly? If so, that's fine. There are probably a number of tools out there to help you, personally I often just create a form anyway but instead of a submit button I have a plain button and add some JavaScript code (using jQuery) to serialize the form and perform an AJAX POST.
As long as the keys for the POST values map to your model fields in the same way they would in an out-of-the-box form, then your action method will still be able to receive the proper model type. On the server-side it doesn't matter if it's from an AJAX call or a normal POST. The difference, however, is that the response for an AJAX call should probably be in JSON format instead of responding with a view.
So instead of this:
return View(someModel);
You might have something like this:
return Json(someModel);
I have 2 gsp's say, "a.gsp" and "b.gsp".
"a.gsp" have combobox, from which user can select options.
My question is that, if the user shift to "b.gsp" and then come back to "a.gsp", the combobox selected option should be still there.
How to achieve this ?
You can do multiple things to achieve this. Depending on your requirements you may:
Use javascript and cookies.
Pass the value selected in the combobox into the controller when you naviate to b.gsp and into a hidden field in b.gsp, but then you have to pass it back to the controller once more when you want to see a.gsp.
Pass the selected value inside session/flash scope
From your question it sounds like you are not fully embracing Grails' MVC architecture and using controllers correctly to prepare data and pass structured data through to your view.
To begin with, rename your controller actions and views to something meaningful rather than a,b. Even if just for testing a small sample, as taking shortcuts can lead to long term bad habits...
Secondly, if you are using a tag then you would use the value attribute to indicate what should be selected.
Read about the tag and its attributes here : http://grails.org/doc/2.1.0/ref/Tags/select.html
Give us more details and perhaps we can help.
Thanks for the clarification, so I'm assuming that there could be any number of ways a user might leave the current a.gsp page and come back, but whatever happens you want the browser to remember the selected option. In this case I would use the jQuery cookie library, its very small, won't impact performance as you're doing very litte work and should be very quick for you to setup.. See: https://github.com/carhartl/jquery-cookie
Set a cookie in an onChange handler based on your selects val() value.
When your page loads (document ready), if you get a value when reading the cookie, then try and set the select value.
On Telerik demo site we can see an example of how to implement kind of functionality: "check all checkbox in a grid's column". But in my case it has 2 disadvantages:
It didn't check all checkbox on all pages.
It didn't save a state of checkboxes on different pages.
Is anybody know how to resolve these issues? Thanks in advance.
As long as I know there's no built-in functionality to do so. The same problem happens when you select records on page one and change to page two, you loose whatever you selected before.
To achieve that functionality you have 2 options (I've used both on previous projects)
1) On each check make an Ajax call to one of your controllers and store whatever you selected on a Session Variable (This can be inefficient if you have a lot of records)
2) Create a javascript variable and store your selections there, and send back to the controller using a json variable or a comma separated values string
As I said, I've used both approachs so it depends on if this works for you or not
Hope it helps
I can't test this, so I'm not 100% sure, but looking at Telerik's example, one reason it's not persisted is because every "page" of the grid requires a postback, and in the controller action result method, they aren't passing in the model (or view model) for the items that are bound to the grid, they're only returning that list of items back to the view, so it will never "save" which items are checked/selected and which ones aren't. You should be able to get around this by making your view model a parameter into the HttpPost action result method and then passing that list back to the view after the post so that it retains which items are selected instead of creating a new one. This won't solve the issue with not selecting all the items, but it should at least retain which ones are selected throughout the pages. I think the reason for it not working with all items is it can only select the ones that are actually being displayed at the time. You may want to do a post (or ajax) to select "all" items.
One of the major reasons for using paging in grids is so that you don't have to retrieve all of the data from the data store and generate a lot of HTML to push to the client.
It's been my experience that most users understand that a "select all" check box only checks the items on the current page. I've not seen a site where checking such a check box would actually check all records, even those I can't see.
If you have an action which will affect more than the current page of records, I would suggest that you add a button which clearly indicates that the action will affect all records, then send a command to your data layer which will perform that action. This will perform better (you don't have to send a potentially long list of ids across the wire) and allow users to understand the repercussions of their action.
I am in the process of writing a web app that includes a reporting form. This form contains a number of radio buttons that allow the user to specify the return data.
There are about 6 different return data 'formats', and each of those has two variations - html data or JSON data for rendering to a chart.
I have begun coding it up and already my form post action method feels wrong.
I basically have a check on the requested data format and return it as needed. Each return type requires its own partial view / json object so there is little room for reusing code.
It feels like each one should have its own action method. Having the form post to different locations based on a radio button choice also feels wrong though.
Switching on report type and then redirecting to the appropriate action in the controller also feels like its not quite right.
Am I approaching this in the wrong way? As it currently stands my controller action contains a lot of code and a lot of logic...
Hope my query makes sense.
Thanks
I don't think there is anything wrong with your approach. To maximize reuse you could:
include reusable templates inside your views
make sure the business/data layer code is the same everywhere (where possible)
I suppose the views you need to return actually are different for each combination of options so whatever approach you take, you are stuck with that.
I wouldn't opt for the client-side approach. You then have code on both the server and the client that has to be updated whenever you change anything. I would keep the code that receives a set of options and determines what to do with them in one place.
I know what you mean about it feeling like each format should be a separate action, but maybe a hybrid approach would make it feel better.
If you set the value of each radiobutton to the name of the action it relates to, you then, in your main POST action, have a parameter that you can use to call the appropriate action in one line of code. You don't have to fudge anything in Javascript, it's easily extensible, and you get your separate actions.
If I understand your problem right you have a lot of switch code in action.
I think you can use Factory pattern. You can create factory that will accept switch parameter as parameter and will return ActionResult instance.
Some users of our application will have read-only access to many of our pages, in our current web forms app this means they see the form, but all of the fields are disabled. We're looking at MVC 3 and searching for the cleanest, most idiomatic way of implementing this functionality.
Some ideas so far:
Some combination of a global action filter and edit templates.
A custom Html helper, something like Html.SecureTextBox etc...
I'm leaning towards number 1, but I'm wondering if any of you guys/gals with more MVC experience have solved this problem in a better way.
I agree with using a base view model, or perhaps just an interface with a "CanEdit" type of property. If you go the interface route, you could set the property in an ActionFilter in the OnActionExecuted method.
To tie it to the view, creating a new HtmlHelper would be pretty easy. I'd use TextBoxFor as the base class, since it has access to the view's model. You can then inspect the property and create the necessary HTML attribute. However, with going this route you will need to create a new helper for each type of input control you need (textbox, select list, etc).
Without knowing all the details of what you are doing, a much simpler idea would be to not provide a Save button for read-only users. The Save button would be driven by one property in the view model (or ViewData, if you like).
Several other people mentioned that a server-side restriction is still needed to prevent people from bypassing the client-restrictions. You will need an action filter for this. This link has a good idea about that.
My preference would be to set a variable in a common base view model (or ViewData), using a global action filter, and then use a bit of jquery to dynamically disable the input fields, delete buttons etc.
$(':input').attr('readonly', true);