How to make fields in QoR model readonly? - go

I have a data model:
type Epg struct {
gorm.Model
Uri string `gorm:";not null;unique"`
Prefix string `gorm:"size:64;not null;default:''"`
Etag string
Updated time.Time
Status bool `gorm:"default:true"`
}
I publish this data model in menu:
EpgResource := Admin.AddResource(&models.Epg{}, &admin.Config{Menu: []string{"Content"}})
Now I can view and edit data via QoR Admin panel. But I want to make values Etag, Updated, Status to be readonly because they are updated by the system.
If I try to make this fields readonly according documentation:
EpgResource.Meta(&admin.Meta{Name: "Etag", Type: "Readonly"})
I got an error. Is it possible to make some fields in data model visible but readonly? How to do that?
Error log trace.
2017/04/25 01:16:04 Finish [GET] /admin/epgs Took 19.59ms
/usr/local/go/src/text/template/exec.go:433
/usr/local/go/src/text/template/exec.go:536
/usr/local/go/src/text/template/exec.go:668
/usr/local/go/src/reflect/value.go:302
/usr/local/go/src/reflect/value.go:434
/usr/local/go/src/runtime/asm_amd64.s:515
/home/rns/golang/src/github.com/qor/admin/func_map.go:1051
/home/rns/golang/src/github.com/qor/admin/func_map.go:220
/home/rns/golang/src/github.com/qor/admin/func_map.go:236
/home/rns/golang/src/github.com/qor/admin/func_map.go:393
got error when render form template for Etag(Readonly): haven't found form
template for meta Etag

That particular error is being caused by qor not finding a template file at .../metas/form/Etag.tmpl, which is presumably needed to actually render the Etag to the form. (You can make the template render a readonly/static element rather than an input)

EpgResource.Meta(&admin.Meta{Name: "Etag", Type: "Readonly"}) would work only on darwin (Mac) machines. But, not on linux machines.
Do the following:
EpgResource.Meta(&admin.Meta{Name: "Etag", Type: "readonly"})
I hope this helps.
Reference: https://doc.getqor.com/admin/metas/hidden-readonly.html#readonly

Related

PUT VS PATCH for operation set template to default

I have to change one value (template) in my entity A:
class A {
private Template template
}
My endpoint looks like:
/warehouse/company/{companyId}/template/default
with body:
class MyDto {
private Long templateId
}
What is the best solution for this operation? I want to change only one value in my entity: based on MyDto I have to fetch template from DB and set A.setTemplate(newTemplateFromDB).
The best option would be PATCH without RequestBody, but request body is necessary...
You should definitely use PATCH because you are partially updating your resource (A) and not completely updating it.
If you would update the complete resource by replacing your DB data with whatever you receive in the endpoint, then you should use PUT.
I just don't get why you say that the best option would be without the request body.

Displaying PUT body format with go-restful and swagger

I am using go-restful and swagger to generate apidocs which is working great. The problem I am facing is that when I add a body parameter to the documentation I would like to specify the DataType and its format. I can specify the DataType (i.e. UserFields), but the format of the JSON does not show in the Swagger UI, which can be very convenient.
Here is an example of what I am talking about:
The following link shows a body parameter and the corresponding JSON/model next to it http://petstore.swagger.wordnik.com/#!/store/placeOrder
In my case, the JSON/model is missing and only the DataType is displayed http://ibounce.co:8282/apidocs/#!/users/PutUserField
Here is the sample Go code is generates the documentation for this specific endpoint.
ws.Route(ws.PUT("/{id}/fields").
To(PutUserField).
Doc("Update user fields").
Operation("PutUserField").
Param(ws.HeaderParameter("Authorization", "username and password").DataType("string")).
Param(ws.PathParameter("id", "identifier of the user").DataType("int")).
Param(ws.BodyParameter("body", "identifier of the user").DataType("UserFields")).
Returns(http.StatusOK, http.StatusText(http.StatusOK), User{}).
Returns(http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized), ApiError{}).
Returns(http.StatusBadRequest, http.StatusText(http.StatusBadRequest), ApiError{}))
UserFields is a struct:
type UserFields struct {
Email string `json:"email,omitempty"`
Phone string `json:"phone,omitempty"`
URL string `json:"url,omitempty"`
Address string `json:"address,omitempty"`
}
Any suggestions will be appreciated.
I figured it out. In the Go code above instead of
DataType("UserFields")
I have to use
DataType("main.UserFields")

MVC3 Error message globalization

I'm really lost trying to create custom generic validation messages for my MVC3 application.
I read many tutorials and the biggest part of them suggest one of these options:
Create an App_GlobalResources folder and inside that put my custom resource, them I change global.asax, passing the string name of my resource to DefaultModelBinder.ResourceClassKey property. Change the resource's build action to "Embeded Resource".
Right click the project, then go properties, click "Resources" tab and create your custom resource. Set it's access modifier to "Public".
The first one didn't work to me, I have the following keys in my resource:
DefaultModelBinder_ValueRequired, InvalidPropertyValue, PropertyValueInvalid, PropertyValueRequired
and none of them was used when my I tried to submit and form with empty value in a required attribute of my model.
I've put this code at global.asax Application_Start method:
DefaultModelBinder.ResourceClassKey = "My_Resource_Name";
With the second method, I've created an resource with the same keys as the first one. None of them was used by default when a property is invalid or empty (I've changed the ResourceClassKey in global.asax too, but without success). But when I added some parameters to data annotation in my model:
[Required(ErrorMessageResourceType = typeof(MyResourceFile), ErrorMessageResourceName = "MyCustomKey")]
When the attribute of that data annotation is empty, my message defined with "MyCustomKey" is used!
But I really don't want to manually set this to all my attributes, I want to replace the default error messages like: "The {0} field is required."
That message is part of DataAnnotations. The default message is compiled into the DataAnnotations assembly in the resource file under System.ComponentModel.DataAnnotations.Resources.DataAnnotationsResources.resources and is RequiredAttribute_ValidationError=The {0} field is required. You can try to download the source, change that part and rebuild it.
There doesn't seem to be a simple global way of changing it. You could try this, otherwise it looks like you are stuck with adding your attribute to every field. Or use something like this:
public class SomeModel
{
[Required(ErrorMessage = "The article is required")]
public string Article { get; set; }
[StringLength(512, ErrorMessage = "Must be less than 512 characters.")]
public string URL { get; set; }
}

Validation of dynamic fields in a MVC

My model looks like
public class Template
{
Id
Title
List<Field> Fields
}
The “Field” Entity contains information like Name, Caption, Type (TextBox/Select/Radio), Options, and validation rules (Range, Required, string length).
The standard validation in MVC is based on DataAnnotations, but I wants to validate (Both client and Server Side) the form dynamically based on Field Metadata which is dynamic and configurable.
Is it possible? Any pointers?
PS. I searched for the similar questions, but not able to find a solid answer.
I had a similar situation, this is how I handled it:
Server Side
When the POST happened I iterated over all the Fields values and did the Validation based on the validation rules I had on my objects. Then you can simply add ModelErrors to the Field object.
Since you push a Template object to the View you can access the Fields by name Fields[x].SomeProperty. Make sure you have a ValidationMessageFor for SomeProperty
ModelState.AddModelError("Fields[x].SomeProperty", "The Error Message you want to show.);
Client side
Make sure your form has an Id so you can access the Validate method().
Then you iterate over all the fields and just add the validation as you please.
For all the validations rules check the validation Jquery documentation.
$('#frmYourForm').validate();
for (var i = 0; i < 'CountOfAllFields'; i++)
{
$('#Fields_' + i + '__Foo').rules('add', { required: true, messages: { required: 'The Foo field is required'} });
$('#Fields_' + i + '__Bar').rules('add', { required: true, messages: { required: 'The Bar field is required'} });
}
I hope I helped you on your way !
Ps, use FireBug to help you find the correct names of the properties and that's how you can link them with the ModelErrors in the modelstate etc.

jqGrid saving a row with nullable columns

So I have a jqGrid on an ASP.NET MVC 3 website. It's loading the data, searching, filtering, and saving rows with the built in pop-up editor. What I can't get to work is saving a nullable property. I'm using LargeJsonResult instead of the built in JsonResult, so an example of a row in the grid is this:
// C# class
public class Row
{
public string A { get; set; }
public string B { get; set; }
public int C { get; set; }
}
// an example object instance, let's say these values come from the DB
var ret = new Row { A = "a", B = null, C = 5 };
// the JSON string sent to the grid will look like this (notice B is omitted)
// "{ A: 'a', C: 5 }"
Now, the grid will show this as:
A B C
a undefined 5
And this brings me to my problem. The pop-up edit form will show "undefined" in the textbox for B, and will also post this to the server. So if I save that to the database, I'll have "undefined" in my DB instead of null.
How do I get jqGrid to preserve the null value round trip? One solution that seems to me very hacky is based on something Oleg solved in another thread:
// override jqGrid serialization
jQuery.extend(jQuery.jgrid.edit, { ajaxEditOptions: { contentType: "application/json" }, serializeEditData: function (data) {
return JSON.stringify(data).replace(/"undefined"/g, 'null');
}});
This will work, but seems dangerous because it's doing mass edits of data without the user's knowledge. In thinking more about it, I guess this is the fundamental problem of saving back null instead of "undefined" or some other string representation of null (empty string, etc.). The desired behavior would be:
if the property is null, and the user doesn't change the value, it posts as null
if the user changes the value, the property is no longer null
Can we get the grid's edit form to behave like this for nullable properties? Or would I have to create a custom edit form that tracks what the user does with a property?
I hope that I understand your problem. In one my applications where I used jqGrid I had once the problem with NULL values. At the time of development of the application I was not sure how to solve the problem and I placed on the server side the text value "(NULL)" instead of null value of one property. The grid was for advanced users who understand what "(NULL)" is. The value "(NULL)" has no sense in the field (one had no user account with the name) and inside of server code for the Edit operation I could distinguish "(NULL)" value from the real field value. In the way I could come over the problem.
In your case you should solve at least two problems:
You should decide how the null value should be displayed. The "undefined" text seems me not the best one. You can solve the problem with the "undefined" text either on the server side (like I did in my case) or with respect of custom formatter. The custom formatter is very simple thing. It define how a cell value should be displayed as a HTML fragment of the <td> contain. You can for example include an additional hidden <span> element or other HTML element or attribute which will save the information that the value was null.
You should solve the problem with decoding of the null value on the server side during Edit operations. You can solve the problem very easy on the server side (like I do with compare of the corresponding field to the "(NULL)") or with respect of custom unformatter on the client side. The custom unformatter will get the information from the grid cell (from the hidden <span> or other hidden HTML element or attribute) and place the information in the server request.
You can look at the demo for the answer to see an example how one can use a hidden <span> to save an additional information in the cell with respect of custom formatter and to read the information later with respect of custom unformatter.

Resources