Expressjs - parsing form array/bracket fields to real arrays - javascript

I'd like to either find some existing middleware or some handy code to transform form fields with square brackets (i.e. 'contact[21][name]')into real arrays for ExpressJS 3.
Something along the lines of:
for(key in req.body){
if(key.isArrayField()) {
//add new array field to req.body and delete old string version from req.body
...
I'd like to to parse infinite depth of brackets. I'm still learning JS/Node so would love some direction.
Thanks

Can you provide some clarification about what you're trying to achieve with this?
Depending on how you're getting the input from the web form in the first place you can easily parse JSON syntax into real objects (including arrays) using JSON.parse() (docs here) which is built into node.js
Using that method you can have an infinite level of nested values (hashes / objects, and arrays) but you'll need some client-side script to put the values there in the first place (jQuery for example).
If you give a fuller example, including the context of the form being submitted, I can probably give better direction...

In my experience you can simply do something like this...
Jade
input(type="text" name="foo[]" value="foo1")
input(type="text" name="foo[]" value="foo2")
JS
app.post('/test', function(req,res){
console.log(req.body)// { foo: [ 'foo1', 'foo2' ] }
console.log(req.body.foo)//["foo1","foo2"]
console.log(req.body.foo[0])//foo1
console.log(req.body.foo[1])//foo2
});
I don't know if this makes sense but this is how you treat them... at least on express 3.0+

I've sort of solved this by using https://github.com/marioizquierdo/jquery.serializeJSON - the issue is/was that if I just submit a POST form to express it doesn't handle brackets as an array so they have to be regexed manually. By parsing the form into JSON using the the plugin I can then submit it through ajax.

Related

MongoDB - How to build query string with [Object] as a field

I'm building up a string in Meteor to drill down into my data from MongoDB.
My data looks like this:
Data
In my Meteor projects JavaScript I have built up the string like so:
const concentrationTier1 = MyCollection.findOne({_id: "85gh43tnb23v4"}).BILL.Sovereign.USD.Short.Low.High.N.ARGENTINA.IssueName00006.ARARGE5203E7;
console.log(concentrationTier1);
But now in my console it is returning the following:
Console
How would I add [Object] to my string to be able to display the next part of the data?
I have tried .[Object] .Object .0 and of course these didn't work.
Can any body help with this one?
Many thanks,
G
You would have to access that array element as in plain normal javascript, like this:
...IssueName00006.ARARGE5203E7[0].concentrationTier1
And the reason is your MongoDB query already returned a document, you're not querying in your database anymore so there's no need to use dot notation to access array elements.

How do I pass an Eloquent model to a Knockout.js view model constructor?

I have a solution (see below), but it's awkward and klunky & I'd like to hear how others have solved this problem.
Here's a simple example to illustrate the problem:
Imagine I have an Eloquent User model and I'm putting together an "edit user" page that uses Knockout to handle value-to-DOM-element bindings.
In my controller method for this page, I'm doing the following:
public function getEditUser($id = null)
{
return View::make("account.edituser")
->with("user", User::find($id))
->with("groups", Group::all());
}
where the Group model is for my access control groups. The user can be a member of zero or more groups and the relationship is set up in the normal way for Eloquent models.
In the template, I have a bunch of elements (text, select, radio buttons, etc.) set up with data-bind attributes to bind my Knockout view model to the elements.
In the <script> portion of the page, I have the following:
var createUserViewModel = function (user, groups) {
return {
id: ko.observable(user.id),
name: ko.observable(user.name),
groups: ko.observableArray(user.groups),
// ...other attributes go here
// the list of available groups
availableGroups: ko.observableArray(groups)
};
};
// instantiate the view model
var viewModel = createUserViewModel(
// note that I'm using Smarty for my templating system. The
// lines below apply the json_encode method and disable the
// htmlspecialchars function which I have set up to encode
// all output by default
{$user|json_encode nofilter},
{$groups|json_encode nofilter}
);
ko.applyBindings(viewModel);
The user argument to the createUserViewModel function will be JSON-encoded, so it will look like this: { id: 1234, name: "Joe Smith", groups: ['group1', 'group2'], ...}
This is a simple example: I have several forms for entering other information which are significantly more complicated than this.
There are a couple of problems with this:
As I said, it's awkward. The source generated by this is difficult to read for larger models.
I suspect there's an XSS vulnerability here, since I'm echoing data via json_encode directly into the body of the script element. I haven't been able to exploit this, but I think someone else could find a way.
But I can't think of another way to do it that doesn't radically change the way the application works (ie. use AJAX calls to retrieve the data).
Can anyone share a better way to do this?
Re (1) you need to look at the very useful mapping which is designed for exactly this - http://knockoutjs.com/documentation/plugins-mapping.html ... this will replace the createUserViewModel function for you, and save you having to manually turn a JSON object into something observable.
Re (2) I'm not expert enough with security and XSS to give an authoritative answer, but it looks OK to me. So long as the user and group data was sanitised before you stored it, then it should be OK to echo it back as JSON. If you're not providing a textbox or other input for a user to type into that then affects this data then there's no angle for an attacker to inject a malicious script. Plus JSON-encoding itself is quite a good sanitisation, in that any JavaScript will just end up as a string. So to be sure, given:
{$user|json_encode nofilter}
will print out some JSON, you could immediately try JSON.parse on it:
var user = JSON.parse({$user|json_encode nofilter})
before you then do anything with it in your script.

Parse.com relations count

I want to query object from Parse DB through javascript, that has only 1 of some specific relation object. How can this criteria be achieved?
So I tried something like this, the equalTo() acts as a "contains" and it's not what I'm looking for, my code so far, which doesn't work:
var query = new Parse.Query("Item");
query.equalTo("relatedItems", someItem);
query.lessThan("relatedItems", 2);
It seems Parse do not provide a easy way to do this.
Without any other fields, if you know all the items then you could do the following:
var innerQuery = new Parse.Query('Item');
innerQuery.containedIn('relatedItems', [all items except someItem]);
var query = new Parse.Query('Item');
query.equalTo('relatedItems', someItem);
query.doesNotMatchKeyInQuery('objectId', 'objectId', innerQuery);
...
Otherwise, you might need to get all records and do filtering.
Update
Because of the data type relation, there are no ways to include the relation content into the results, you need to do another query to get the relation content.
The workaround might add a itemCount column and keep it updated whenever the item relation is modified and do:
query.equalTo('relatedItems', someItem);
query.equalTo('itemCount', 1);
There are a couple of ways you could do this.
I'm working on a project now where I have cells composed of users.
I currently have an afterSave trigger that does this:
const count = await cell.relation("members").query().count();
cell.put("memberCount",count);
This works pretty well.
There are other ways that I've considered in theory, but I've not used
them yet.
The right way would be to hack the ability to use select with dot
notation to grab a virtual field called relatedItems.length in the
query, but that would probably only work for me because I use PostGres
... mongo seems to be extremely limited in its ability to do this sort
of thing, which is why I would never make a database out of blobs of
json in the first place.
You could do a similar thing with an afterFind trigger. I'm experimenting with that now. I'm not sure if it will confuse
parse to get an attribute back which does not exist in its schema, but
I'll find out, by the end of today. I have found that if I jam an artificial attribute into the objects in the trigger, they are returned
along with the other data. What I'm not sure about is whether Parse will decide that the object is dirty, or, worse, decide that I'm creating a new attribute and store it to the database ... which could be filtered out with a beforeSave trigger, but not until after the data had all been sent to the cloud.
There is also a place where i had to do several queries from several
tables, and would have ended up with a lot of redundant data. So I wrote a cloud function which did the queries, and then returned a couple of lists of objects, and a few lists of objectId strings which
served as indexes. This worked pretty well for me. And tracking the
last load time and sending it back when I needed up update my data allowed me to limit myself to objects which had changed since my last query.

How do we use the output of visualsearch.js?

I'm interested in using the visualsearch.js control for my website but, having read through the documentation, I am still unclear regarding how to effectively obtain the output search collection data. Based on the example, the output string is constructed through serialization of the search collection. However, I was wondering if there is a way to access the search collection in a more array-like fashion (so that for/in loops can be used) rather than having to parse a single serialized string. Ultimately, I need to construct SQL queries from the search collection data.
If there is an even more efficient or appropriate way of accessing the search collection data, please let me know!
Thanks!
as far as i know there are 2 ways to fetch data from visual search
it is also directly explained in their documentation in usage #4
like you said, the stringified version of the search.
visualSearch.searchBox.value();
// returns: 'country: "United States" state: "New York" account: 5-samuel title: "Pentagon Papers"'
or the facetted object to loop over
visualSearch.searchQuery.facets();
// returns: [{"country":"United States"},{"state":"New York"},{"account":"5-samuel"},{"title":"Pentagon Papers"}]
as you can see, this option gives you an array, per facet that was filtered on, and for each asset the value that was entered.
mhmmm.. ok, the answer is not so straightforward. I would suggest you to get some practice with backbone structure just making some modification to the todo-list app. It is a great startpoint. So you get familiar with some of the wonderful backbone.js methods for collections
The Basic idea is the following:
With visualsearch you can obtain a list of "facets", that is to say an array of key/values objects.
var myFacets = visualSearch.searchQuery.facets();
//my facets is then something like [{"field1":"value1-a"},{"field2":"value2-c"}]
after this you can use myFacets elements to iterativrely filter you collection with the WONDERFUL filter method hinerithed from _underscore lib.
How to do it? You can use the _.each method in the underscore lib
_.each(myFacets,function(facet){
myCollection=myCollection.filter(function(item){
return item.get(facet.get('category')) == facet.get('value');
});
});
}
Here you use the filter method of backbone.js, which returns only the values are true according to your clause. So, you filter your collection once for each single facet. It is like telling to javascript: "Return me only the elements of the collection which match with this facets (value)", and you do it iteratively for all the different facets you got.
Hope this helps.
Ah.. one last thing, just to mess ideas up :-) :Visualsearch is built on backbone.js, and the searchQuery object is nothing but a backbone Collection, so you can use the methods and the properties of the basic backbone collection. Read this line again if this is not clear, because this can be a key point for future implementations! :-)
I suggest you to have a look at the search_jquery.js file in the lib/js/models folder. It's very interesting...

How do I remove the square brackets at the end of a JS variable name during AJAX calls?

I currently have the following javascript array:
var stuffs = ['a', 'b'];
I pass the above to the server code using jQuery's load:
var data = {
'stuffs': stuffs
};
$(".output").load("/my-server-code/", data, function() {
});
On the server side, if I print the content of request.POST(I'm currently using Django), I get:
'stuffs[]': [u'a', u'b']
Notice the [] at the prefix of the variable name stuffs. Is there a way to remove that [] before it reaches the server code?
This is default behavior in jQuery 1.4+...if you want the post to be &stuffs=a&stuffs=b instead of &stuffs[]=a&stuffs[]=b you should set the traditional option to true, like this:
$.ajaxSetup({traditional: true});
Note this affects all requests... which is usually what you want in this case. If you want it to be per-request you should use the longer $.ajax() call and set traditional: true there. You can find more info about traditional in the $.param() documentation.
When an array is submitted using a GET request, through a form or AJAX, each element is given the name of the array, followed by a pair of optionally empty square brackets. So the jQuery is generating the url http://example.com/get.php?stuff[]=a&stuff[]=b. This is the only way of submitting an array, and the javascript is following the standard.
POST requests work in exactly the same way (unless the json is sent as one long json string).
In PHP, this is parsed back into the original array, so although the query string can be a little strange, the data is recieved as it was sent. $_GET['stuff'][0] works correctly in PHP.
I'm not sure how Django parses query strings.
The [] indicates that the variable is an array. I imagine that the appending of the [] to your variable name is Python/Django's way of telling you it is an array. You could probably implement your own print function which does not show them.

Categories