Vue: Collect all (or some) form values simultaneously - forms

I'm trying to understand if I can achieve with vue.js the same handy process I use to follow with vanilla/jquery to collect simultaneously all (or only some of) the form fields I need.
When dealing with forms usually I never submit them the old school way, instead, I add a class my-update to the form fields I want to send and then I loop them this way:
let objectToUpdate = {};
$(".my-update").each(function(index, element) {
objectToUpdate[$(this).data("db-field")] = $(this).val();
});
Then I just pass the object to an Ajax POST call and send it to the backend API.
With Vue, it's way simple to get data since we have the property (usually called data) already available within the Vue instance but the problem is if I just send the this.$data it will catch not only the properties (all of them without choice) but also all methods included in the object (getter/setter, ...).
Do you have any best practice or suggestions to share to achieve the same I usually do with a couple of lines of jquery but in Vue?

Usually in Vue form controls are binded to data via v-model. Let's say my Vue instance/component is like:
new Vue({
data: {
user: {
name: '',
surname: '',
phone: '',
}
},
methods: {
send() {
// send this.user through http
}
}
});
And my template is like:
<form #submit="send">
<input name="username" v-model="user.name" />
<input name="surname" v-model="user.surname" />
<input name="phone" v-model="user.phone" />
<button> send </button>
</form>
In such scenario, you have all the user information in your component/instance via this.user. You don't need to send this.$data at all if you create an object to manage your form fields (like this.user in this example).

Related

Kendo UI MVVM Datasource binding to html input element

newbie to kendo
The kendo datasource only returns arrays and my RESTful api returns a client as an array of one element.
However, I cannot seem to bind the 'Name' field of the client to an html input box.
I can however consume the data if I put it in a 'ul', as shown in the below code. I know the json response is well formed because I can console.log(obj[0].Name);
I attempted to return obj[0] in the data: of the datasource but that just broke everything. (no slice error message, as it tries to slice up the array).
I'm sure this is easy but I must be just thinking about this all wrong...
Html and js below:
<div data-role="view" data-title="Client Detail" data-model="app.clientView">
<!-- this does not work -->
<input data-bind="value: app.clientView.data"/>
<input data-bind="value: app.clientView.data[0].Name"/>
<input data-bind="value: app.clientView.data.Name"/>
<!-- this works -->
<ul data-role="listview" data-source="app.clientView.data" data-template="client-template"></ul>
<script type="text/x-kendo-template" id="client-template">
<a href="components/clientView/view.html?id=#: ID #">
<div>#: Name #</div>
<div>#: LastActivityOn #</div>
</a>
</script>
app.clientView = kendo.observable({
data: new kendo.data.DataSource({
transport: {
read: {
url: app.uri + "clients/69", //+ id,
type: "get",
dataType: "json",
beforeSend: function (req) {
req.setRequestHeader('X-authKey', app.key);
}
}
},
schema: {
data: function (response) {
console.log(response);
var obj = $.parseJSON(response);
console.log(obj[0].Name);
return obj;
}
}
})
});
Kendo UI MVVM value bindings cannot point to a Kendo UI DataSource instance. Only source bindings can do that.
In your case, rework your implementation and add some new fields to the viewModel (app.clientView), which can be used for value bindings. It is OK to populate these fields after the DataSource instance receives its data.
On a side note, there is no need to specify viewModel fields verbosely by including the viewModel reference in the bindings configuration. You only need the field names there. Check the Kendo UI MVVM demos.

Grails forms & URL mapping

I am writing a Grails app where I would like to setup a form that allows a user to type in an image ID number and this value will be passed to a controller / action that retrieves the image from S3 for the given image ID.
The desired url would be of the format example.com/results/1234. I have setup the following URL mappings:
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
"/results/$id?" {
controller = "s3Image"
action = "getS3Image"
}
"/"(view:"/index")
"500"(view:'/error')
}
}
The following is how I have setup a form:
<g:form controller="results" method="get">
<input type="text" name="id" class="input-xxlarge" placeholder="http://www.example.com">
<button class="btn btn-inverse">Submit</button>
</g:form>
However this seems to submit the form to example.com/results?id=12345.
How would I alter my form or mappings such that I can produce the desired url after form submission?
Thanks!
<g:form controller="results" method="get">
will generate an HTML form whose action URL is /results (the reverse URL mapping for a controller named "results" with no action or id). When this form is submitted, the browser will add ?id=1234 to the end of this URL because the form method is GET. This is not something you can influence in your URL mappings on the server side.
Instead, you should have your form POST to a different controller action that redirects to the getS3Image action. The redirect will have access to the ID on the server side, so can generate the friendly-looking URL for the redirect.
UrlMappings:
"/results/$id?" {
controller = "s3Image"
action = "getS3Image"
}
"/findImage" {
controller = "s3Image"
action = "find"
}
S3ImageController:
def find() {
redirect(action:"getS3Image", id:params.id)
}
def getS3Image() {
// as before
}
GSP:
<g:form controller="s3Image" action="find" method="post">
<input type="text" name="id" class="input-xxlarge" placeholder="http://www.example.com">
<button class="btn btn-inverse">Submit</button>
</g:form>
Derek,
what you are seeing is correct behaviour. For the GET request you have two things
URL of request
Parameters
Parameters are appended after urls using urlencode and separated by &, so, when you have form with URL http://mydomain.com/controller/action/, and in this form you have two fields: id, name, then, upon submission, they will be passed like this: http://mydomain.com/controller/action/?id=3&name=someName
URLMappings are mapping only URL part of it. So, in your example UrlMapping are matched only to /results/ and id is not passed.
But that is ok, since you can still access the id parameter in your controller, just do it like this (inside s3Image controller):
def getS3Image() {
def id = params.id
}
Try very simple change in UrlMapping:
"/results/$id?" {
controller = "s3Image"
action = "getS3Image"
id = $id
}
and then for sure you have the id accessible in the s3Image controller via:
def id = params.id
I think you have two problems here. First, UrlMappings rules are matched in order of appearance, from top to bottom. First rule that grails matches is "/$controller/$action?/$id?". Move your rule "/results/$id?" above and it should take precedence. - check comment below post.
Your second mistake is declaration of form. I think you've meant:
<g:form controller="s3Image" method="getS3Image">

Passing values from a form to a new action

Ok guys i have a question, if this is my Form , and is generated for every item in the DB, i want to send the item with the quantity specified.
to send the quantity , from this razor view
#using (Html.BeginForm("AddToCart", "Prices"))
{
string qtname = "qt" + #item.id;
<div>
<input id="#qtname" name="#qtname" class="quantity" type="text" value="0" readonly="readonly" />
</div>
<input type="submit" value="Adauga" class="addToCart" />`
}
i need just these?
[HttpPost]
public ActionResult AddToCart(ProductsModel Products, string qtname)
{ }
and do i need some html.hidden for passing along the item.id too?
In the form you are sending only the qtname parameter as input field, whereas your controller action also expects a ProductsModel parameter which is never sent. If you want to bind it you will have to create input fields for all properties of this view model.
But in your case a better solution would be to simply include the id of the product as hidden field and then fetch the corresponding product from your datastore given this id:
[HttpPost]
public ActionResult AddToCart(string id, string qtname)
{
ProductsModel products = _repository.GetProduct(id);
...
}

Simple form to edit only one field of model in Spring MVC

What is the best way to change data of, for example, User?
I got lots of properties like 'username', 'city', 'phone' and when I want to edit just one field ('password'), I have to do this:
<form:form action="editUser.htm?id=${user.id}" commandname="user">
<form:hidden path='username' />
<form:hidden path='city' />
<form:hidden path='phone' />
<form:input path='password' />
....
In my controller action is defined:
#RequestMapping(value = "/editUser.htm", method=RequestMethod.POST)
public ModelAndView ordertypeedit(#ModelAttribute("user") User user,
BindingResult result, HttpServletRequest request)throws Exception{
userTypeValidator.validate(orderType, result);
if(result.hasErrors()){
(...)
return new ModelAndView(...);
}
orderTypeDAO.update(orderType);
return new ModelAndView(...);
I don't like to set all the to my action form... If I miss it, it shows error 'column 'username' cannot be null".
It depends if your properties are validated or mandatory on that form:
If not, then you don't need to submit them with your form:
<form:form action="editUser.htm?id=${user.id}" commandname="user">
<form:input path='password' />
and in your controller you will get user object with only user parameter.
Alternative way is to pass regular (not Spring MVC) form and create inside user object with only id and password properties.
you can use simple (without spring tags) form with one input and get it in controller using #RequestParam

Spring MVC - bind form elements to a List<Long>

Is it possible to bind a form element to a List<Long>?
ie. <form:input path="formValues[0]" /> binding to an element in List<Long> formValues; in the form backing object?
When I try this, it fails because Long does not have a default constructor new Long().
I've worked around it by creating a dummy holder class
class DummyLong {
private Long value;
...
}
making the list in the formbacking object a List<DummyLong> and changing the form tag to <form:input path="formValues[0].value" /> but this seems unnecessarily hideous and I'm sure there must be a better way. Haven't been able to find it though.
Use List<Long> formValues with <form:input path="formValues" />