Asp MVC 2: Typed Editor Template - asp.net-mvc-2

(I reference this tutorial in this text)
I want to use the Html.EditorFor (or Html.Editor) helpers.
If a UserControl needs additional data it is passed via
...EditorFor(model => model.Album, new { Artists = Model.Artists, ... })
In the UserControl it's accessed via ViewData[stringKey], ie
... new SelectList(ViewData["Artists"] as IEnumerable, ...
To me this smells a little fishy as I would prefer a strongly typed ViewModel which ensures that specific data is available.
I'm now a little bit stuck as I don't know wheater there's a "typed way" to find or I should accept this way as-is.
How did you solve this issue? Any help appreciated!
Lg
warappa

I would probably change my view model so that I don't need to pass this additional information. You could make for example an album has a collection of artists. Now all tha you will have to do is:
<%: Html.EditorFor(model => model.Album) %>
And in your editor template:
<%: Html.DropDownListFor(x => x.SelectedArtist, new SelectList(Model.Artists)) %>

Related

How do I generate a form using a model with single table inheritance?

I have a model Company that has a type field. There are two subclasses Fleet and Dealer.
I know the inheritance is working so I'm now working towards the views working too. However the views/companies/_form.html.erb is producing this error when I click edit on a specific company object on my webpage:
undefined method `dealer_path' for #<ActionView::Base:0x000000000418c0>
Here is the form_with tag:
<%= form_with(model: company, class: "contents") do |form| %>
*CONTENT*
<%end%>
I want to generate the form based on what company type I am looking at and for all the fields to be populated with their corresponding data.
I found this warning on the ROR site (https://guides.rubyonrails.org/form_helpers.html):
When you're using STI (single-table inheritance) with your models, you can't rely on record identification on a subclass if only their parent class is declared a resource. You will have to specify :url, and :scope (the model name) explicitly.
But I do not understand exactly what this means and I believe it is the key to my solution. I wish there was an example of this situation on that guide.
Any help or suggestions are welcome and appreciated!
UPDATE
I changed the form_with tag to be:
<%= form_with(model: [:company #company], class: "contents") do |form| %>
and from my understanding this now generates the URL companies/:id/edit
This is closer, and now brings me to the companies edit page but I can't update now because the changes don't persist.
My NEW question now is, what routes should I have set up?
If I'm on localhost:3000/companies and I click 'show company', should this take me to /companies/id: or take me to /dealer/id: / /fleet/id: ?
I have managed to route the app so it will take me to /companies/id regardless of the type value of the object. This works well and all CRUD is working well now too.
I didn't log exactly what it was I changed this time as I just reverted to a previous commit and rebuilt from there.

sails blueprint view iterates over hidden properties of empty object

I am new to sails, and trying to output a basic list coming from the find action from the blueprints.
Using an example view from the docs:
<ul>
<% _.each(data, function (project) { %>
<li><%= project.name %></li>
<% }) %>
</ul>
and checking the value of matchingRecords in the node-inspector returns [] (which i expected).
The view however lists 2 items with value undefined, see image below:
If I add data into the model, it iterates over the json returned by the blueprint char by char. I must be doing something wrong, but I am kind of stumped. I originally used Jade, and thought maybe there is something wonky with the template adapter, but as I said, ejs gives me a very similar result.
What I am doing wrong ?
It seems there is a bug in sails at the moment of writing.
An issue has been opened on Github https://github.com/balderdashy/sails/issues/3932

Multiple form inputs for the same field

I have a Rails model called request_form. In the form I have multiple boxes that can be selected, similar to the "What can we craft for you section" in the following site http://mostlyserious.io/get-started/
I have a field called number_of_guests that can be a handful of values depending on which section is clicked. I plan on using javascript to grab the value of the clicked element and assigning it to the request_no_of_guest param. However, in the form I have that same field rendered 5 times to allow for each selection. What is the best way about this? Is there a better way to handle this? I thought about creating a controller method that loops through each instance of that request_no_of_guests param and determining which instance is populated and then sending that up.
Is this the best way to handle this case?
Well as you did not provide any useful detail I will answer as I understood the question.
Let’s have a quick look at what this might look like. To do so, we’ll imagine a demo app into which you can enter the name of a professor and select their various areas of expertise.
Professor has a field expertise which is String.
The form can be as follows:
<%= label_tag 'expertise_physics', 'Physics' %>
<%= check_box_tag 'professor[expertise][]', 'Physics', checked('Physics'), id: 'expertise_physics' %>
<%= label_tag 'expertise_maths', 'Maths' %>
<%= check_box_tag 'professor[expertise][]', 'Maths', checked('Maths'), id: 'expertise_maths' %>
alter app/controllers/professors_controller.rb
from
params.require(:professor).permit(:name, :expertise)
to
params.require(:professor).permit(:name, expertise:[])
Then in app/models/professor.rb
before_save do
self.expertise.gsub!(/[\[\]\"]/, "") if attribute_present?("expertise")
end
and in /app/helpers/professors_helper.rb
def checked(area)
#professor.expertise.nil? ? false : #professor.expertise.match(area)
end
This way you can grab the different values selected in the form into the expertise attribute, however this is not recommended if you are planning to query the selected options. The right way would be create a new model called Expertise and then create the relationship professor has_many expertises.
But if you are looking for something simple, then use the above code.

Binding two objects of the same type in an action

I have a page that collects information on two objects of the same type. When the page is submitted the action that handles the processing of the information submitted is attempting to use model binding, something similar to:
public ActionResult Submit(Person parent, Person child)
{
//Do some stuff
}
It manages to bind one of them successfully but not the other. Does anyone have any suggestions/resources etc that could help me get this to work?
If needed I can gut/rename and post the actual code for the various pieces.
The solution to this is very much similar to the solution to my question that I posted the other day (I wouldn't at all call this a dupe though).
What you need to do is just include the parameter name in your inputs, eg:
<%: Html.TextBox("Parent.Name") %>
.....
<%: Html.TextBox("Child.Name") %>
and it should all automagically work.
(I think this is MVC2 only, you didn't mention whether you were using 1 or 2)
Would it make sense to have a ParentChild Model with two person instances in it?
I don't think I've seen any examples like this trying to bind two models on post.

Do you use <%: %> or <%= %> for html helpers in ASP.NET MVC 2.0?

I know they now have this in ASP.NET MVC 2.0 <%: Model.CustomerName %>
So when you make HTML helpers is it better to use this way now (provided that you do not want to do HTML encoding)?
Using <%: %> should be used whenever you display user entered/submitted data to make your web pages safer.
But sometimes it's just not viable to HTML encode everything. What if you do want to preserve some HTML formatting? In this case you will have to use the regular <%= %> statement. Let's think of an example where this is the case.
Real-life example
Let's say you have some web content where users can submit their comments. You would like to provide the ability to preserve some formatting (at least line breaks). In this case you will have to preserve <br/> elements when later displaying these comments. You have two choices:
Cleanup and format comments when you store them in the DB - in this case you would strip all HTML tags from submitted comments and then replace all new lines (\n) with <br/>. When you would like to display this comment you could then call <%= Comment %>
Cleanup and format comments when you display them - in this case you would most probably call this <%= Html.Encode(Comment).Replace("\n", "<br/>") %>
Which one is better/safer depends on each particular case, but cleaning up HTML tags is always a nice step to include in any of the two. Everything also depends on allowed formatting definition. Should those be entered as regular tags or something similar to markdown or something completely different depends on you and the code in the end will most certainly depend on it.
Second approach advantages/disadvantages
advantage
Let's say that you do provide some formatting capabilities but after about a year or so you decide to change formatting rules or something related to them (which is quite common). If you use the second approach the new rules will work with old comments as well, because they were stored as is, while the first approach will loose its significance with old data. One example would be if you'd auto-detect web links in these comments in the cleanup/formatting phase. Using the first approach all links in old comments would stay unclickable, but if you used the second one even older comments with links would format them as clickable.
disadvantage
Second approach uses much more processing than the first one, because every comment would have to be preprocessed each time it's displayed, while in the first approach they're processed only once when we store them in the DB. Depending on the formatting/cleanup complexity and quantity of comments on each page this may become significant.
If processing does become a problem you should think of an alternative to use first approach, but while cleaning up and re-formatting the comment you'd save both versions in your DB. Original submitted comments as well as processed ones. So when you do change formatting rules you can always reformat old comments because you stored originals.
Yes, you always want to use <%: Model.CustomerName %> from now on where you can. Only in very specific cases should you use <%= %> but try not to use it at all.
If you are creating your own html helpers that you don't want to be encoded, then just return a MvcHtmlString from them.
E.g. This is a extension method I created to display a tick icon if the passed in value is true.
public static MvcHtmlString MECross(this HtmlHelper html, string value, string text)
{
if (Convert.ToBoolean(value))
{
string spanTag = string.Format("<span class=\"replace icon-cross\" title=\"{0}\"><em></em>{1}</span>",
html.AttributeEncode(text),
html.Encode(text));
return MvcHtmlString.Create(spanTag);
}
return MvcHtmlString.Empty;
}
Note that I Encode and AttributeEncode anything that could be dangerous in my extension method and then return a MvcHtmlString.
HTHs,
Chares