Rails Dynamic Multi Model Form attributes - ruby-on-rails

This problem has been killing me. I played around with Ryan Bates complex forms, but I can't quite figure out my problem.
I have this schema:
Location has_many :targets
Target has_many :target_classifications
All locations are shown on the page. A user may create a target for any location dynamically through jscript, which then adds a table row under the location 3 selects (that contain available classifications to the target) and a target value. Any number of targets can be created for any location before clicking save.
I'm using rjs to render a target_partial, which has this code:
I'm using fields_for in this way:
for each select. When sumbmitted, I get this hash:
"new_targets"=>
{"7"=>[{"id"=>"13"}, {"id"=>"15"}, {"value"=>"67", "id"=>""}],
"4"=>
[{"id"=>"12"},
{"id"=>"15"},
{"value"=>"23", "id"=>""},
{"id"=>"11"},
{"id"=>"16"},
{"value"=>"67", "id"=>""}]},
So, it separates each target by location ("7" and "4" in this case), but doesn't separate each target. What I want is this:
"new_targets"=>
{"7"=>[
{"target"=>[{"id"=>"13"}, {"id"=>"15"}, {"tonnes"=>"67"}]}
],
"4"=>[
{"target"=>[{"id"=>"12"},{"id"=>"15"},{"tonnes"=>"23"]},
{"target"=>[{"id"=>"11"},{"id"=>"16"},{"tonnes"=>"67"]}
]
}
so I can iterate through each target for each location. I can't seem to add in a new [target] brace in my field_for method (it blows up), but that's kind of what I want to do. Any thoughts?

I don't know if you are doing this, but you need to specify a string instead of the object when using fields_for. I can't see the codes you have in your partial, so I may be way off. Anyway, the way I do it is in a helper:
def fields_for_target(target, &block)
prefix = target.new_record? ? 'new' : 'existing'
fields_for("location[#{prefix}_target_attributes][]", target, &block)
end

This sort of issue is discussed here:
http://wonderfullyflawed.com/2009/02/17/rails-forms-microformat/
But it seems to be a rails 2.3 solution (not an option for me). Basically, I want a form like they've posted on the site:
<input name="creator[widget_attributes][0][id]" />
<input name="creator[widget_attributes][0][name]" />
<input name="creator[widget_attributes][0][price]" />
<input name="creator[widget_attributes][1][id]" />
<input name="creator[widget_attributes][1][name]" />
<input name="creator[widget_attributes][1][price]" />
Just some way to create a unique identifier for each target (or in this case, widget attribute) I want to add. Kind of tough given that a new target is added with jscript. I feel like there should be some way for rails to automatically do this for me

Easy. Look up accepts_nested_attributes_for. :)

Related

adding an id attribute to q-input

Say I have the following q-input:
<q-input
v-model="form.email"
inverted-light
color="white"
stack-label="Email:"
type="email"
#blur="$v.form.email.$touch"
:error="$v.form.email.$error"/>
I'd like to be able to make it so that if the domain of the email is mydomain.com that the form action will change to another website (without csrf protection) and the POST will be made to that website instead of the main one.
To do this I was thinking I could use jQuery. eg. $('#email').val().replace(/^.+#/, '') == 'mydomain.com' then change the form action and submit.
The only problem is: I don't know how to set an id attribute on q-input.
Any ideas?
As of early Quasar 1.4.2 (November of this year) you can specify the id value on the resulting html generated by q-input by using the "for" property (see the end of the behavior properties: https://quasar.dev/vue-components/input#QInput-API).
So, for example, you could add for="myInputId":
<q-input
v-model="form.email"
inverted-light
color="white"
stack-label="Email:"
type="email"
#blur="$v.form.email.$touch"
:error="$v.form.email.$error"
for="myInputId"
/>
The id attribute with value "myInputField" will end up on the resulting <input> element in your HTML.
Not using the "for" in the elements gave me a lot of headaches because the Jest snapshot generated random IDs

I need an explanation about how to use Grails (with different controllers)

I'm trying to create a little and basical Twitter-like site with Grails.
Here is the main part of my project arborescence (UserCwitter handles users, MessageCwitter handles messages and GroupCwitter handles groups like followers/followings) :
I'm trying to insert a text field to write a new message in the index (here it's index_final.gsp).
So I added this piece of code (in every controller my function to create a new user/message/groupe is called save()) :
<g:form action="save">
<fieldset class="form">
<g:render template="form"/>
</fieldset>
</g:form>
But I don't know why, the form that appears is the one to create a new user and not a message.
Why and what should I do ?
Thanks for your help. Sorry if this is something really easy or even stupid, I'm really new to Grails.
From render tag documentation, related to template attribute:
Note that if the value of the template attribute starts with a '/' it
will be resolved relative to the views directory. This is useful for
sharing templates between views. Without the leading '/' it will be
first be resolved relative to the current controller's view directory
then, failing that, the top level views directory.
So you should use
<g:render template="/messageCwitter/form"/>
if you want to render form template that is in messageCwitter folder.

Creating objects with hidden field values passed from Rails

Im quite new to Angular, so how Im approaching this might be entirely wrong, but some general advice on which direction to take with this would be much appreciated. More or less what I'm trying to do is use Angular to create new "Like" objects (similar to facebook 'likes'). They contain two values, user_id (which used to be set by rails as current_user.id via devise's helper method) and post_id.
My problems:
current_user is not accessible in Angular's ng-controller
You can't provide default input values directly into the form like so:
`
<input type="text" value="<%= current_user.id %>" ng-model="newLike.user_id" >
So more or less what I'm asking is, how could I manage to set default values of the inputs for user_id and post_id. I've come across recommendations for using ng-init, however, from everything I've seen it seems that this only allows setting default input values from the angular controller
EDIT:
It took shockingly long for it to dawn on me to pass the variables in as params to addLike so I've managed to successfully create new objects based off of the current_user.id & act.id.
Rails way
You can write inside your .html.erb (or .js.erb) javascript code that initializes a global / passes a parameter with the value of current_user.id
Angular way
Using ng-init is perfect here (better over the rails way). As Mark Rajcok commented ng-init can be used from your HTML like this:
<input type="text" ng-init="newLike.user_id='<%= current_user.id %>'" ...>

Grails: Load data on one ComboBox depending on another

Let's say I have a combobox with the options GENERAL, AIR, GROUND, and SEA
<g:select name="group" from="${['GENERAL', 'AIR', 'GROUND', 'SEA']}" valueMessagePrefix="default.category" value="${tipoN}" />
And then another combobox that loads certain information depending whether you select GENERAL, AIR, GROUND, or SEA.
Let's say GROUND has 3 options, FedEx, USPS, DHL, but AIR has complete different ones, AIRPLANE, JET, HOT AIR BALLOON.
The name of the other <g:select> should be "commodity"
I thought about creating a javascript file and treating everything like HTML but I did some google research and is not as simple as I thought.
Does anyone know what would be the best way to do this?? Thanks in advance!
FG
Sounds like you'll want to use AJAX for this. One way you could do it is by using a combination of templates, and domain objects:
// grails-app/domain/ShippingOption.groovy
class ShippingOption = {
String method, // can be 'ground', 'sea', 'air', or 'general'
name // can be 'fedex', 'ups', etc.
def options = {
def meth = params.method ?: "general"
def comList = ShippingOption.findByMethod(meth)
render(template:"shippingList", model: [ commodityList: comList ])
}
}
And the template:
<!-- grails-app/views/_shippingList.gsp -->
<g:each var="opt" in="${commodityList}">
<option value="${opt.name}">${opt.name}</option>
</g:each>
And in your gsp with the select box on it:
<!-- ... other stuff is before here ... -->
<g:select name="method" from="${['GENERAL', 'GROUND', 'SEA', 'AIR']}"
onchange="${remoteFunction(action:'options', update:'commodity',
params:''method=' + this.value' )}" />
<select id="commodity"></select>
I'm sure I've messed up some syntax, and you'll definitely have to refactor this a bit to work with your code. But at least you've got the general idea.
And to use them, add them to the database as ShippingOptions. Here's one way to do it.
["fedex", "ups"].each { name ->
def so = new ShippingMethod(method: "ground", name: name )
so.save()
}
PS: You'd also be able to render the shipping methods dynamically, as well.
See also: remoteFunction, g:select, templates, and AJAX
I would consider re-designing your UI and changing the flow.
A drop-down dependency that you are describing suggests the form should probably be split and adopting a 'wizard-like' solution will result in a more user-friendly and solid solution that will work also without JavaScript.
I have a worked example using AngularJS and Grail here:
http://wordpress.transentia.com.au/wordpress/2013/12/24/keeping-up-with-the-joneses/
(apologies if this is not appropriate SO 'style', but I dont' think that posting 100s of lines of code and verbiage is appropriate, either).

Using HTML forms in ASP.NET MVC?

It seems like everything I look up on this subject has either changed since the release or is wildly different from eachother.
I just want to create a simple form in my view.
Should I be using the Html.BeginForm()/TextBox()/EndForm() methods or should I be using a plain-jane HTML form? Which is preferred?
This is what I have so far:
<%=Html.BeginForm("Create", "Product", FormMethod.Post); %>
<%=Html.TextBox("productTextBox", "Enter a shoe name"); %>
<input type="submit" name="createButton" value="Create Me!" />
<%=Html.EndForm(); %>
What is the "correct" way to create a simple form with a button and textbox in ASP.NET MVC and allow me to submit the data in the form to the /Product/Create action?
How do I then access the form data from within that method? Some people seem to use a "FormCollection" and others just do a Request.Form method. Which way should I use?
Can someone enlighten me?
The Form helpers are the recommended way because it allows you to provide a controller, action and other route data and the URL is auto-generated based on your routes (in Global.asax). The advantage is, if you decide to change your routes, you don't have to update every URL in your site.
The only reason I'd use an actual "<form>" tag was if I needed extra control over the markup that I couldn't get from Html.Form (I can't think of an example right now). Even if you choose to do that, you should use the "Url.Action" helper to get a URL from routing data. For example:
<form action="<%= Url.Action("Create") %>">
As for your second question, I'd suggest using the Model Binder. Check out ScottGu's Blog for some details on this.
Have a look at Link.
It's German text but the code should be understandable.
Have you looked at this:
http://weblogs.asp.net/scottgu/archive/2009/03/10/free-asp-net-mvc-ebook-tutorial.aspx
It's from the horse's mouth, and is up-to-date with the final release.

Resources