Angular ng-model send data as array to rails-api - javascript

When adding the ng-model directive to an HTML element, I usually do so with it attached to an object. However, before sending the HTTP request, a portion of the data should be an array of objects.
In my rails-api I have a User model and an Address model. The user has many addresses and the address belongs to a user.
The goal is to just take in the parameter via strong params and save each of the addresses (received as JSON, array of objs) and have them each be related to the user.
Currently, i'm numbering them and doing some extra manipulation prior to shipping the data off to the API. Ex:
<input type="text" ng-model="form.address1">
And then for the second, ng-model="form.address2".
How can I setup an array of objects using the ng-model attribute and add objects onto the array in my HTML?

You can bind to array too:
<input type="text" ng-model="form.address[0]"> Address 1
<input type="text" ng-model="form.address[1]"> Address 2
Demo: http://plnkr.co/edit/owpAqLLlgOjBKfqHSZ4U?p=preview

Related

Javascript reading multidimensional form

This has driven me "doo-lally" this afternoon!
A vendor (Zaxaa) uses a multi-dimentional form thus:
<form method="post" name="zaxaa" action="xxxx">
<input type="text" name="products[0][prod_name]" value="ABC">
<input type="text" name="products[0][prod_type]" id="pt" value="FRONTEND">
</form>
** This is my understanfing of how a multdimentional array is set up, and it seems to pass the variables to the server OK.
However, dependant on what other inputs are set to on the test form, the [prod_type] (and others) may need to change to "OTO" This is obviously going to be a javascript function, (but not the variant that starts with "$" on code lines ... whatever that type is!)
I have tried
document.zaxaa.products[0].prod_type.value
document.getElementById('products[0][prod_type]').value
document.getElementsByName('products[0][prod_type]').value
but in everycase, I get "products is not defined". (I have simplified the form as there are ten product[0] fields)
I've solved it... mainly a glaring error on my part. The getElementById worked fine ... except in my test script I'd used getElementById[xxx] and not getElementById(xxx)!! ie "[" rather than "(" Does help if you get the syntax right!
But I will take notice of those other methods, such as enclosing both array arguments in ["xxx"].
getElementById didn't work because the only one of those elements that has an id is the second input, with id="pt".
On any modern browser, you can use querySelector to get a list of the inputs using a CSS selector:
var nameInput = document.querySelector('input[name="products[0][prod_name]"]');
var typeInput = document.querySelector('input[name="products[0][prod_type]"]');
Then use their value property. So for instance, to set the name to "OTO":
document.querySelector('input[name="products[0][prod_name]"]').value = "OTO";
Use querySelectorAll if you need a list of relevant inputs, e.g.:
var nameInputs = document.querySelectorAll('input[name="products[0][prod_name]"]');
Then loop through them as needed (the list as a length, and you access elements via [n] where n is 0 to length - 1).
Re
* This is my understanfing of how a multdimentional array is set up...
All that HTML does is define input elements with a name property. That name property is sent to the server as-is, repeated as necessary if you have more than one field with that name. Anything turning them into an array for you is server-side, unrelated to JavaScript on the client. (The [0] is unusual, I'm used to seeing simply [], e.g name="products[][prod_name]".)
You can access it in this syntax:
document.zaxaa['products[0][prod_name]'].value
document.zaxaa.products[0].prod_type.value
The name is a single string, not making a nested structure to access the input. It would need to be
document.zaxaa["products[0][prod_type]"].value
// or better:
document.forms.zaxaa.elements["products[0][prod_type]"].value
The complicated name does only serve to parse the data into a (multidimensional) array on the server side, but all data will be sent "flattened".
document.getElementById('products[0][prod_type]').value
The id of your input is pt, so this should work as well:
document.getElementById("pt").value
document.getElementsByName('products[0][prod_type]').value
getElementsByName does return a collection of multiple elements - which does not have a .value property itself. Instead, access the first element in the collection (or iterate it completely):
document.getElementsByName('products[0][prod_type]')[0].value

Serializing HTML form array to Javascript array

I have a form containing a list of text fields
<input type="text" name="list[]" value="">
<input type="text" name="list[]" value="">
I'm running some custom jQuery to validate the input and do a few other things, before displaying a JSON chunk to the user. What I want to achieve is these elements should become a standard javascript array a la:
{"list":["something","something else"]}
Is there a simple call I can make on the specific element to pull it in as an array, something like this?
var jsonVars = {};
jsonVars['list'] = $("input[name=list]").getArray();
With the structure you have and assuming you want to get the values you could do:
var jsonVars = {};
jsonVars['list'] = $('input[name="list[]"]').map(function(){return this.value;}).get();
You can use $('input[name="list[]"]').serializeArray() but will return in a different format as array of objects (with name and value).
There's jQuery's serialize function. This topic is similar to yours and might give you some more advanced insight.

javascript add array item to form value

I have a form with a hidden field:
<input type="hidden" name="newdesc[]" id="newdesc" />
I have an autolookup and a plus button so the plus button adds the field value of the autolookup to an array:
newdesc_a.push(document.getElementById('autocomplete1').value);
var x=document.getElementById("businesslist");
x.innerHTML=newdesc_a;
document.getElementById('newdesc').value = newdesc_a;
(newdesc_a is previously declared as an array)
It updates the div OK (businesslist) but does not assign the value to the newdesc.
I am sure it is simple but it is driving me mad!
Given the name="newdesc[]" attribute, I assume PHP on the server side. When you submit a key two or more times, only the last value is available in the script via $_REQUEST. In the case of a key ending with [] , instead, PHP builds an array and make it available to your script via $_REQUEST['key']. Note that this behavior is application-specific, there's nothing like an array at the HTTP level.
Now, you want to pass an array from the client side (Javascript) to the backend (PHP). You have two options:
Use a proprietary format, eg separate values by commas or colons, and split the string on the server side (or you can use an existing format like JSON, XML, ...)
Take advantage of the PHP syntax for passing arrays
It seems you want to adopt the 2nd way, so you will want to submit a form like the following
<input name="email[]" value="joel#example.com" />
<input name="email[]" value="mark#people.com" />
<input name="email[]" value="bill#hello.com" />
PHP will be able to access a plain array in $_REQUEST if you build your form like this. Now, you have the problem of building the form programmatically on demand. This is the best I can think of (jQuery):
var email = $("#autocomplete").value;
// if you really need to keep emails in an array, just
// emails.push(email);
$('<input type="hidden">').attr({
name: 'email[]',
value: email
}).appendTo('#myForm');
You want to assign a particular value of array to that element?
You can use like this.
document.getElementById('newdesc').value = newdesc_a.index;
where 'index' is the index of array. replace it.

Binding from Html Dom elements to json objects

I am working on a search panel, where I want to bind the data entered in these input elements to a search parameter json object. This search parameter will then be used for, you guessed it right, searching.
For example, user when searching for another person and he can specify the name, age or sex of the person on the page. I have json object which has, as its members Name, Age and Sex. I want to bind the inputs entered in the corresponding input elements on the page to this JSON object automatically, so when the user clicks on the Search I will just use whatever the json object has as a search param.
This is primarily to avoid having to - first find the corresponding element and then assign the corresponding member of the JSON object to the input in this field.
I could find jquery plugins (Databind) , which do the other way round i.e. transfer the values of a JSON object to the input elements.
Thanks in advance!!
I think you are confusing your terminology: presumably you mean a Javascript object.
Anyway, your object or json string need to be constructed when the user clicks "Search". It will be difficult/fiddly to assign these as the user enters text into the input fields. You could use the onblur event but you're just making unnecessary work for yourself.
Far easier is just to give each input field an id, and when the user clicks "Search" you build your object, then JSONify it. Here's how you might do it (not tested!):
<input type="text" id="name" />
<input type="text" id="age" />
...
var obj = { };
obj.name = document.getElementById('name').value;
obj.age = document.getElementById('age').value;
...
var json = JSON.stringify(obj);

jQuery AutoComplete Fill Array

I'm attempting to use jQuery's autocomplete feature, and after reading several posts I still have two questions:
1) I've gotten autocomplete to work with the code posted at the bottom, however I need the array titled "data" to be filled from our database. I've been trying to use different methods to fill this via AJAX. I tried using $.get and $.ajax. What is the correct syntax to accomplish this?
2) This array will be big, I will have 60,000 plus values if I just fill the array once. I was wondering if it's possible to perform an AJAX request to fill the array every-time the user enters a new letter? Is this better to do, or just fill the array with all values at once? By better, which taxes the system less?
//This code works
<script type="text/javascript">
$(document).ready(function(){
var data = "Facebook Gowalla Foursquare".split(" ");
$("#search_company").autocomplete(data);
});
</script>
//display company live search
echo('<form id="form" method="post" action="competitor_unlink.php" onsubmit="return">');
echo('Company: <input id="search_company"/>');
echo('<br/>');
echo('<button type="submit" value="Submit">Submit</button>');
echo('</form>');
Look at this demo - it's what you want to do (get data using ajax):
http://jqueryui.com/demos/autocomplete/#remote
You can pull data in from a local
and/or a remote source: Local is good
for small data sets (like an address
book with 50 entries), remote is
necessary for big data sets, like a
database with hundreds or millions of
entries to select from.
Autocomplete can be customized to work
with various data sources, by just
specifying the source option. A data
source can be:
an Array with local data a String,
specifying a URL a Callback The local
data can be a simple Array of Strings,
or it contains Objects for each item
in the array, with either a label or
value property or both. The label
property is displayed in the
suggestion menu. The value will be
inserted into the input element after
the user selected something from the
menu. If just one property is
specified, it will be used for both,
eg. if you provide only
value-properties, the value will also
be used as the label.
When a String is used, the
Autocomplete plugin expects that
string to point to a URL resource that
will return JSON data. It can be on
the same host or on a different one
(must provide JSONP). The request
parameter "term" gets added to that
URL. The data itself can be in the
same format as the local data
described above.
The third variation, the callback,
provides the most flexibility, and can
be used to connect any data source to
Autocomplete. The callback gets two
arguments:
1) A request object, with a single
property called "term", which refers
to the value currently in the text
input. For example, when the user
entered "new yo" in a city field, the
Autocomplete term will equal "new yo".
2) A response callback, which expects
a single argument to contain the data
to suggest to the user. This data
should be filtered based on the
provided term, and can be in any of
the formats described above for simple
local data (String-Array or
Object-Array with label/value/both
properties). It's important when
providing a custom source callback to
handle errors during the request. You
must always call the response callback
even if you encounter an error. This
ensures that the widget always has the
correct state.
Here's an example of how to specify a URL that will return the results from the database as JSON using the jQuery UI autocomplete plugin.
$("#search_company").autocomplete({
source: "/Search", // <-- URL of the page you want to do the processing server-side
minLength: 4 // <-- don't try to run the search until the user enters at least 4 chars
});
Autocomplete will automatically append a querystring parameter named "term" to the URL so your search page will need to expect that. Not sure what server technology you're using but since I'm a .NET developer here's an example in ASP.NET MVC :)
public ActionResult Search(string term) {
var results = db.Search(term); // <-- this is where you query your DB
var jqItems = new List<jQueryUIAutoCompleteItem>();
foreach (var item in results) {
jqItems.Add(new jQueryUIAutoCompleteItem() {
value = item.CompanyId.ToString(),
id = item.CompanyId.ToString(),
label = item.CompanyName
});
}
return Json(jqItems.ToArray(), JsonRequestBehavior.AllowGet);
}
jQueryUIAutoCompleteItem is just a data container that represents the JSON format that the autocomplete plugin expects.
public class jQueryUIAutoCompleteItem {
public string value { get; set; }
public string label { get; set; }
public string id { get; set; }
}
You're correct that sending the whole 60,000-record list to the client's machine doesn't sound like the best solution. You'll notice that Google only shows you a handful of the most popular matches in its autocomplete, as to many other websites.
You could shorten the list by waiting for the user to type two or three letters instead of searching on the first one.
You could do page chunking in the list (it goes by various names). That is, only return the top 10 or 15 matches. The user can get more of the list by scrolling or by clicking on a "Show More Results" link. You have to write (or search for) all the javascript code for this, of course.
It might be a bit late to this post but for others that find it. I created a plugin for jquery and the jqueryui autocomplete control that works with Foursquare. You can read the post and download the plugin at Foursquare Autocomplete Plugin

Categories