I'm using Grails 2.3.x
Imagine the domain class: Book (String Author, String Title)
When I'm creating a book I need the Author field and the Title field editable.
When I'm editing a book I need the Author field NON-editable and the Title field editable
I know that there is a Domain Constraint (editable: false), but that doesn't work with the second case. It only adds this tag to the readonly="readonly"
I also tried this: How to conditionally disable a form input field
But it seems that: "${mode == 'edit'}" is always false.
Thank you very much
That link you provided assumes that a variable flag called mode will be passed into the view to determine whether you are editing or not. To do this, you will need to pass mode into the view from your controller like this:
def edit(Long id) {
[bookInstance: new Book(), mode: 'edit']
}
That will force the ${mode == 'edit'} portion to be true.
Related
So I have a standard Kendo grid in MVC with 2 non-editable columns. What I would like to achieve is to enable editing of all columns only within the newly added rows.
Example: There's 4 rows already in the grid, first 2 columns non-editable. User clicks "Add new", a new record appears in the grid with everything editable.
Try adding an editable function handler to your column definition, something like this:
{
field: "salary",
editable: function (dataItem) {
return dataItem.isNew();
}
}
Please note: you will need to have specified an id column in your model definition for this to work, for details see isNew documentation:
Checks if the Model is new or not. The id field is used to determine if a model instance is new or existing one. If the value of the field specified is equal to the default value (specified through the fields configuration) the model is considered as new.
I would like to add a data-other-for attribute to a text input, to link it to a select, so that it can be used to capture a value not present in the select when the user selects 'Other' in the select. The attribute's code will determine which value or description is in fact 'Other', and if so, enable the text input and maybe make it mandatory.
It seems like the only way to do this is by creating a new helper, because going via a ValidationAttribute I can only add preset validation HTML attributes to my text input. Or go large and write a whole new metadata provider.
You could try to implement a custom ModelBinder.
Say, in the select you would have:
new SelectListItem(Text = "Other", Value="bind:propertyName", Selected = False);
Then in the overriden BindModel, you simply look for bind: in the model properties and when found, copy your value from there.
After this, you should be able to add normal validation attributes to your select list.
I have an Edit action/view for my User object, but only want a few fields to be editable.
I've set up the view to bind to the User object, and am using Html.EditorFor() for the few fields that I want to be editable.
I noticed in my User object on Post:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditUser(Mynamespace.User user)
{ }
that only the fields that I provided .EditorFor() controls for actually have any data.
I tried using Html.Hidden(Model.ID) for one of the fields that i didn't want to be editable, but it is null in the new User object created from model binding.
So, my question- How do I bind where only a couple of the fields should be editable?
Thanks!
It sounds like you probably want to start thinking about using a View Model that is specific to the form/input that you're dealing with. But in the short term, ....
You could bind to a FormCollection parameter instead and copy the values manually, OR...
you can use the TryUpdateModel method to populate this existing user object with the new data.
Here's the documentation for TryUpdateModel:
http://msdn.microsoft.com/en-us/library/dd470756.aspx
It's still possible for malicious users to send phony form-values that map to real properties on your model, so to protect against this (like an employee changing his salary property with a simple form hack) you can introduce an interface that contains the white list properties that you allow.
Here's an example:
public interface IUserEditableFields
{
string Username {get;set;}
string Email {get;set;}
}
//... in the controller action
if(TryUpdateModel<IUserEditableFields>(user)) {
//validation passed
//only Username and Email were editable
}
This is a good resource on how to do this:
http://css.dzone.com/news/aspnet-mvc-think-before-you-bi
Are you using the strongly-type helper for the hidden field or is it exactly like you've typed. If you've got it exactly as typed, then the name of the hidden field is the value of the id, not the name of the property on the model (ID). You might want to change it to:
<%= Html.Hidden( "ID" ) %>
or (if using strongly-typed helpers)
<%= Html.HiddenFor( m => m.ID ) %>
Ben's answer is largely correct, in that a ViewModel might be more appropriate, and short of that, TryUpdateModel can be used. However, I add that in that case, rather than requiring the domain object to implement a new interface, you use the overload TryUpdateModel<T>(T, string[]), which allows you to whitelist the updateable properties in a string array by name.
I have a model (entity class) Newsletter. I pass a list of Newsletter to a View and display the list of Newsletter in a table with each Newsletter across a row. Besides each Newsletter row, there is a checkbox. I will select the Newsletters that I want to send by checking the checkbox and clicking on a send button.
How can I pass the selected Newsletters to the controller?
Thanks.
In your view:
<input type="checkbox" name="newsletterIds" value="<%=newsletter.Id%>"/>
In your target controller:
public ActionResult SendNewsletters(int[] newsletterIds)
{
... do something with the ids...
}
Do something like this in your view:
<%= Html.CheckBox("cbNewColors", true) %><label for="cbNewColors">New colors</label>
in your controller, do something like this:
bool bChecked = form["cbNewColors"].Contains("true");
Simply add a boolean value called Selected to your entity class which, when passed back to the controller, will tell the controller which newsletters were selected in your list.
If you don't want to "pollute" your entity class with client metadata, you could inherit from it and add the selected bool in your derived class.
Alternatively your model can simply contain a separate list that holds references to selected newsletters or some unique identifier with which individual newsletters can later be selected from an original list.
You'll have to do some manual work, since MVC adds hidden fields for each checkbox, and relies on the model binder to deal with the value true,false coming in from the form submission (if the box was checked).
Assuming you have unique IDs available in your views, I'd recommend the following:
Manually create the checkboxes (i.e. don't use the Html helper) with the same name
< input type="checkbox" name="newsletters" value="nl_[id]" id="nl_[id]" />[name]< /label>
Accept a string[] newsletters parameter into your action that handles the post. (You may need to accept a string, and then split it on commas, I don't remember array newslettersArray = newsletters.Split(','); ;)
Convert the string into a list of newsletter IDs doing something like this:
var ids = newsletters.Select(n => int.Parse(n.Substring(2)).ToList();
I have a page that displays a list with a of elements with a large number of elements, each of which has a boolean property, representing an Enabled and a Disabled state.
I need to provide the user with a link for each list item, and the link text must show the opposite status (so if the item is enabled, the link text must display 'Disable').
When the user clicks the link for a Disabled, the corresponding link text for the item must change to 'Enable' (and vice versa).
I would like to NOT reload the entire list for each click, just the text of the ActionLink itself, so my question is:
Is it possible to update just an ActionLink itself when the user clicks the link, or do I have do handle this using custom javascript?
As far as I remember, you can add HTML attributes to the "a" tag by newing up an anonymous class as the last param on most overloads.
Off the top of my head this can be written like the following:
Html.ActionLink("Name", "Action", "Controller", new { #class = 'updateId' });
(You may be able to do this with an ID which would be preferable over a class - if not just use a unique class name to avoid updating multiple items.)
Then you can use javascript to access the class "updateId" and change the inner html.
In the case of jQuery:
$("a.updateId").html("NewName");
This can be done with a custom user control contained within the element to update. A writeup of the solution can be found here. No custom client-side scripting is necessary.