How to draw a checkbox in razor MVC3 - asp.net-mvc-3

#model IEnumerable<FacetValue>
<ul>
#foreach (var association in Model)
{
<li>
**#Html.CheckBox("association",association.IsSelected) #Html.Label("association", association.Text)**
#if (association.IsSelected == true)
{
<input type="checkbox" id="association" class="left" value="#association.Text" checked="checked"/>
}
else
{
<input type="checkbox" id="association" class="left" value="#association.Text"/>
}
<label>#association.Text</label>
</li>
}
</ul>
I am using the code that starts with #if vs the #htmlCheckBox.
1. The layout is messed up
2. It doesn't display is messed up and displays check box in one place and text in another place.
3. a hidden value is generated for every check box.
Now the question is how can I display the the contents how I want without the #if else logic.

There is no need to reinvent the wheel.
Here is a very good post to look:
Asp.net MVC Multiple check-boxes in an array
If it still does not cover your scenario then look at this pre-existing discussions:
Discussion 1, Discussion 2

To bind complex objects, we need to provide an index for each item to insure correct postback. That's why we need to change IEnumerable<> to IList<> (or you can created another variable and populated it with Model.ToList()). Than we need to change foreach() to for(), so Html.CheckBoxFor can correctly create IDs and NAMEs that will insure correct postback.
#model IList<FacetValue>
<ul>
#for (int i = 0; i < Model.Count(); i++)
{
<li>
#Html.LabelFor(model => model.Model[i].IsSelected, Model[i].Text)
#Html.CheckBoxFor(model => model.Model[i].IsSelected)
</li>
}
</ul>

you can customize your extension method of Check box with property additional Visible, and in the creating of checkbox , you pass the value of visible

Related

Is't possible to get access to <ul> and <li> during submiting form

I have view with controller. I would like to know if it is possible to get access to ul and li? I don't want to do ajax call and pass these elements as parameters. Li elements are added on client side dynamically. this.Request.Form show me only 'name' variable without 'list'. Any advices?
<form action="#Url.Action("Filter")" method="POST">
<ul data-role="listview" data-inset="true" data-filter="false" name="list">
#foreach (var item in #Model.Items)
{
<li value="#item">#item</li>
}
</ul>
<input type="text" name="name"/>
<inpu type="submit" value="Filter"/>
</form>
and controller:
[HttpPost]
public ActionResult Filter(string name, List<string> list)
{
// working with list
return RedirectToAction("Index");
}
thanks
No,
It is not possible to access <ul> and <li> on post back.
BTW, the following code is generates <li> on server not on client
#foreach (var item in #Model.Items)
{
<li value="#item">#item</li>
}
If you wish to access Items (#item) on server, there are other ways to get those that do not require access to <ul> or <li>
For instance, you can emit a hidden (#Html.HiddenFor) element in each <li> in your loop.
You can try the following.
I'm not sure what your view model looks like, but it seems like a list of string values? So then it will look like this in your view model:
public class YourViewModel
{
public List<string> Items { get; set; }
}
In your view try the following:
<ul>
#for (int i = 0; i < Model.Items.Count(); i++)
{
<li>
#Html.DisplayFor(x => x.Items[i])
#Html.HiddenFor(x => x.Items[i])
</li>
}
</ul>
When you post then these items should still be in the list.
It might not be a perfect solution but it can guide you on the right track.
I hope this helps.

Multiple form in MVC 3 and Ajax

My page in working perfectly with postback. My problem is that it's kind of anoying every ingredients or subtitles that people submit, it reloads the entire page. So, I though that it could be a good way to learn a little bit of ajax... I've read a lot of article, and I got confused. Some people are using Ajax.Beginform and others are using the $.ajax from jQuery inside an event of jQuery (submit for example). I've read that the second approach is better but I don't know if it's possible with the way my form is done.
Here is the important part of my View. To summarize, I have a list of subtitle, and each of the subtitle can contain a list of ingredients. One of the form can submit ingredients, and the other can submit subtitle. The first one can appear multiple time (in each of the subtitle).
<div id="Ingredients">
<h2>Ingrédients</h2>
#foreach (RecettesMaison.Models.Subtitle sub in Model.Subtitles)
{
<h4>#Html.DisplayFor(modelItem => sub.Name)</h4>
<ul id="ing#nSubtitle">
#foreach (RecettesMaison.Models.Ingredient ing in sub.Ingredients)
{
<li>#Html.DisplayFor(modelItem => ing.QuantityAndName)</li>
}
</ul>
using (Html.BeginForm("AddIngredient", "Recipe", new { subname = sub.Name }, FormMethod.Post))
{
#Html.HiddenFor(model => model.IDRecipe)
<a name="IngredientSection" ></a>
<input class="field required span6 text-box single-line" id="nameingredient" name="nameingredient" />
<input type="submit" class="btn btn-success" value="Ajouter un ingrédient" />
}
nSubtitle++;
}
#using (Html.BeginForm("AddSubtitle", "Recipe", FormMethod.Post))
{
#Html.HiddenFor(model => model.IDRecipe)
<a name="SubtitleSection" ></a>
<input class="field required span6 text-box single-line" name="Name" />
<input type="submit" class="btn btn-success" value="Ajouter une catégorie d'ingrédient" />
}
</div>
My first approach was that if a submit is successful, I would "refresh" the two foreach with the new data. But the approach I've seen on must tutorial is to use a partial view and refresh only the partial view inside of a div. But in my case, my Html.BeginForm would be inside the partial view so I don't think it would work. I also think about just appending html at the end of my list but it will only work of the ingredient. So the best way would be to refresh both for each
So, my general question
How can I do that? :)
Thanks!
Ajax.BeginForm vs .ajax()
Both accomplish the same thing. Ajax.BeginForm will hide the javascript details so .ajax() will probably give you a better foundation in understanding the pattern especially if you ever need to work outside of MS technologies.
AJAX with Partial Views
It's entirely possible and there are many examples on the web even here on SO. The general idea is you're just replacing a div with partial view content retrieved via AJAX.
If the div is static, then your jquery selectors are quite simple.
If the div is dynamically generated, then you'll need to do some DOM traversing to find the target div.
Without seeing your attempts it is hard to give you specific help. I suggest you start with a simple example with a single partial view and form and update it using AJAX. Then you can move to a more complex situation with multiple forms once you understand the mechanics.

Show/hide button: put result into POST variable

I have a long list of links in my website's menu. I show the first three links per default, and I have a "Show/hide" button for the rest of the links.
I would like to be able to change the default value (show or hide) according to the visitor's preference.
--> So the default value is "hide" to start with. If the visitor clicks "show" and then clicks a link, I want the next page to be "show" per default. If he then clicks hide, default is "hide".
Below is my menu. 1-2-3 are always shown, 4-5-6 are shown or hidden.
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<div class="liste-cachee">
<div class="quotecontent">
<div style="display: none;">
<li>4</li>
<li>5</li>
<li>6</li>
</div>
</div>
</div>
<input type="button" value="Plus / Moins" onclick="if (
this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != 'block') {
sendMenuDisplay('block');
this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'block';
} else {
sendMenuDisplay('none');
this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; }" />
</ul>
My question is: How can I save what the visitor choses (show or hide), put it in a $_POST variable and use it as the default value on the next page?
Thanks for your time and help
You could POST or PUT the value and put in a cookie or a session attribute for use in subsequent pages. You could also POST or PUT the value using ajax and put the value in a cookie or session attribute for later use. You could also store the value in a database and use across user-sessions.

How to get ID of element by using Html.BeginForm()

I have the form and some code below.
#using (Html.BeginForm("Insert", "Question", "POST"))
{
<div id="add_tag">
<div id="list_tag">
<span class="post-tag" id="2">Phi kim<span class="delete-tag" title="Xóa Tag này"></span></span>
<span class="post-tag" id="22">Hóa Vô Cơ<span class="delete-tag" title="Xóa Tag này"></span></span>
<span class="post-tag" id="1">Lý<span class="delete-tag" title="Xóa Tag này"></span></span>
</div>
<div class="tag-suggestions hidden">
</div>
</div>
<div class="form-sumit clear">
<input type="submit" id="submit-button" value="Post your question" />
</div>
}
And my Insert action in QuestionController like this
[HttpPost]
[ValidateInput(false)]
public ActionResult Insert(FormCollection _form)
{
//my code here
}
I want to get id of span tag nested in by using Html.BeginForm and FormCollection. How can I do that? Plz someone help me. Thanks a lot.
When you click on submit button, form collects all input values inside this form and send to the server with the following format: inputId=inputValue. Span isn't the input control inside the form and form does not collect its value or another information to send to the server. You can generate hidden input control and set the id value to it. And then at the server side in the action you can get it from FormCollection.
[HttpPost]
[ValidateInput(false)]
public ActionResult Insert(FormCollection formCollection)
{
//for example all hidden input controls start with "hidden_tag" id
//and end with your number of tag:
var allNeededKeys = formCollection.AllKeys.Where(x => x.StartsWith("hidden_tag"));
var listOfId = allNeededKeys.Select(formCollection.Get).ToList();
}
Good luck.
I'm pretty sure you can't. You can use fiddler to see if they're posted back to the server but I don't think they are.
You should use hidden fields to post the span's id to the server.
Is the view strongly typed?

MVC Razor - Create / Edit view best practice

I'm working with MVC 3 / Razor for the first time and it seems odd that all the examples and VS scaffolds for create and edit views all have separate HTML views for these concepts.
There is really not much difference between many Create/Edit forms so I was wondering why I can't find examples of people using a single Update form that can be used by both Create and Edit actions.
I have gotten an Update.cshtml view working but was wondering about how it talks to the Edit or Create action method on the controller.
My questions are:
Anyone have a quick answer to talking to the controller, or
Anyone know of a tutorial showing good practice for working this way, or
Is there some good reason for keeping the Create/Edit views separate when the HTML is often the same.
Cheers Dave
This (kind!) of question is asked before: ASP.NET MVC - using the same form to both create and edit
Basically you can create a partial view and include it on your Create and Edit view.
Scott Guthrie has a nice post about Partial Views.
(I've read about this somewhere, but can't find it, I'll update this post when I do find it)
Be mindful that answers to your question should also be driven by business need (and roles). The scaffolding does provide separate functionality, which in some cases is the preferred implementation.
CREATE and EDIT functionality is often pretty much identical from a technical (programming) perspective. This can lead a technical person to think that the functionality should be combined in order to implement a more efficient technical solution. However, any technical implementation must be in response to business need, which might require separation (e.g. by business role) of these concerns.
For example, a business may require that the role which CREATEs business objects is not the same one as EDITs them. In this case, the implemented web pages may not be seen by the same roles (and people) at all.
If you implement CREATE and EDIT using common functionality but the business need is for role separation, you must still implement "role checking" before rendering the required view/partial view/etc. In such cases, separate views can be a preferred implementation.
I do this. I don't know if it's best practice but it can be nice. There are some situations where a completely separate add/edit view could be useful though. Also, if you're using ViewModels then as far as I can tell you're stuck using the same ViewModel for both add and edit. In theory they should both have their own ViewModels.
Here's how this looks for me:
AddVideo.cshtml
#model Multimedia.MediaVideoViewModel
#{
Layout = "~/Views/Shared/LiveSubLayout.cshtml";
}
#section AdditionalHeadContent {
}
<div class="page-header">
<h1>Add a new video</h1>
</div>
<div id="add-video" class="row-fluid">
#Html.Partial("_VideoForm", Model, new ViewDataDictionary { { "ActionKeyword", "Add" } })
</div>
EditVideo.cshtml
#model Multimedia.MediaVideoViewModel
#{
Layout = "~/Views/Shared/LiveSubLayout.cshtml";
}
#section AdditionalHeadContent {
}
#if (ViewBag.Success)
{
<div class="alert alert-success">
<button class="close" data-dismiss="alert">×</button>
<h3><strong>Video saved!</strong></h3><br/>
<div class="btn-group">
Preview this video
#Html.ActionLink("Add Another Video", "AddVideo", "Multimedia", new { Model.Id }, new { #class = "btn" })
#Html.ActionLink("View all media", "Index", "Multimedia", null, new { #class = "btn" })
</div>
<p>or continue editing below...</p>
</div>
}
<div class="page-header">
<h1>Edit video <small>#Model.Title</small></h1>
</div>
<div id="edit-video" class="row-fluid">
#Html.Partial("_VideoForm", Model, new ViewDataDictionary { { "ActionKeyword", "Edit" } })
</div>
_VideoForm.cshtml (partial)
#model Multimedia.MediaVideoViewModel
#{
string actionKeyword = ViewData["ActionKeyword"].ToString();
}
<div class="span6">
#using (Html.BeginForm("editvideo", "multimedia"))
{
<label class="control-label" id="embed-url">Paste video URL here:</label>
<div class="control-group">
#Html.TextBoxFor(model => model.EmbedUrl, new { #class = "span12", id = "video-url", placeholder = "ex: http://www.youtube.com/watch?v=PoAGasPLh30" })
<button class="btn disabled" id="get-video" title="Tooltip">Get Video</button>
</div>
<div class="video-meta">
<h3>Video Information</h3>
<label class="control-label">Title:</label>
<div class="control-group">
#Html.TextBoxFor(model => model.Title, new { #class = "span12", id = "video-title" })
#Html.ValidationMessageFor(model => model.Title, "A title is required", new { #class = "label label-important" })
</div>
<label class="control-label">Description:</label>
<div class="control-group">
#Html.TextAreaFor(model => model.Description, new { #class = "span12", id = "video-description" })
</div>
<h3>Categories</h3>
<div id="tag-search" class="well">
<label class="control-label">Search tags:</label>
<div class="controls"><input type="text" class="typeahead" /></div>
#if (Model != null)
{
foreach (var category in Model.Tags)
{
#Html.Partial("_TagFragment", category)
}
}
</div>
<hr />
#Html.HiddenFor(model => model.Id)
#Html.HiddenFor(model => model.ThumbnailUrl, new { id = "thumb-url" })
<input type="submit" id="video-submit" name="video-submit" class="btn-large btn-primary" value="#actionKeyword video" />
</div>
}
</div>
I edited these down a bit so something might be missing but this should give you the general idea.
here's how i do it, it's not always the best practice (it depends on the case)
1/ combine the controller actions for create and edit
public PartialViewResult Creedit(string id = null)
{
if (id == null)
{
// Create new record (this is the view in Create mode)
return PartialView();
}
else
{
// Edit record (view in Edit mode)
Client x = db.ClientSet.Find(id);
if (x == null) { return PartialView("_error"); }
// ...
return PartialView(x);
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Creedit(Client x)
{
if (x.id == null)
{
// insert new record
}
else
{
// update record
}
}
2/ combine the edit and create views into one view i called Creedit
// if you need to display something unique to a create view
// just check if the Model is null
#if(Model==null){
}
so i have 1 view and 2 actions (1 post and 1 get) instead of 2 views and 4 action.
Look into MVC scaffolding in nuget as well, when it generates the view files it does so explicitly creating a creatandedit partial and having the create page and edit page use that partial.

Resources