Multiple form in MVC 3 and Ajax - asp.net-mvc-3

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.

Related

Make browsers remember input fields without submitting (or having at all) a form?

I have a web application based on bootstrap (so, using jquery), and I'm trying to convert a classic html form-based search form to an ajax search form (to avoid page reload).
In the classic form-based, the button sends the html form as post, and the action page returns a table of results below the same form.
something like:
<form action="/search" method="post">
<input type="text" name="searchterms">
<button type="button" onclick="submit();">Search!</button>
</form>
In the ajax version, there is no form, but just a text field and the button calls a dosearch() function which makes an ajax request to a back end script which return search results, which are then used in a target DIV, showing a table of results, below the search input+button.
<input type="text" name="searchterms">
<button type="button" onclick="dosearch();">Search!</button>
Both work fine, but the second way avoid the browser to "collect" previously used search terms - I guess because there's no "submit".
My users like this "previous search terms" suggestion, and I would like to add it back, if possible, in the search "ajax" form.
I also tried to create an html form anyway, which encloses the input and the button, adding this event to its tag:
onSubmit='dosearch();return false;'
(if I don't return false, the form is submitted and action page loaded), like:
<form onsubmit='dosearch();return false;'>
<input type="text" name="searchterms">
<button type="button" onclick="dosearch();">Search!</button>
</form>
but even this seems not to work: new search terms are not "remembered" and suggested typing in the field...
I thought maybe my dosearch() function could add (most recent) search terms into a session/cookie but then I would need to read those stored values and create, each time, a sort of "dropdown" list for the input field, just as browsers usually do automatically... it should be not complicated but probably overkill...
Is there any way to make browsers "remember" inserted values even without submit? If not, what workaround is best/easiest?
edit: I've just found this
input remembered without using a form
but maybe after 5 years something changed?
I just tried to change the "button" type, to a "submit", and in this way it seems to work... page is not reloaded, ajax fills the results div and my new terms are remembered...
like:
<form onsubmit='dosearch();return false;'>
<input type="text" name="searchterms">
<button type="submit" >Search!</button>
</form>
it seems that if the "submit" is triggered through a "submit" button (even if it return false) the browsers stores input field values...
you need to do with ajax
<form onsubmit='dosearch();return false;'>
<input type="text" name="searchterms" id="searchTerm">
<button type="button" onclick="dosearch();">Search!</button>
<script type="text/javascript">
function dosearch(){
val = $("#searchTerm").val();
$.ajax({
url: "LoadProduct.php?val ="+val,
type: "GET",
processData: false,
contentType: false,
}).done(function(respond){
$("#LoadProductTd"+no).html(respond);
$(".chzn-select").chosen(); $(".chzn-select-deselect").chosen({allow_single_deselect:true});
});
}
</script>
so you can create LoadProduct.php file and in file you will get your search term n $_GET['val']
so you can use this for your query

Ajax.BeginForm not creating a form tag inside the dom

In my MVC project I'm using an ajax form to dynamically update some search results based on a modified search term.
When rendering the Ajax.BeginForm() Method, it doesn't render a <form> tag on the page (in the DOM)
everything is set up fine, Jquery, Unobtrusive and AJAX are all referenced and I have working Ajax.BeginForm instances elsewhere
#using (Ajax.BeginForm("FilterSearch","Attachment", new AjaxOptions()
{
OnComplete = "updateSearchResults",
HttpMethod = "POST"
},new{}))
{
#Html.HiddenFor(model => model.AccountId)
#Html.HiddenFor(model => model.ContactId)
#Html.HiddenFor(model => model.OpportunityId)
#Html.TextBoxFor(model => model.SearchTerm, new { placeholder = "Search Term", #class = "header-search-box" })
<input type="submit" class="header-search-input" />
}
is just rendering inside the DOM as
<input id="AccountId" name="AccountId" type="hidden" value="">
<input id="ContactId" name="ContactId" type="hidden" value="">
<input id="OpportunityId" name="OpportunityId" type="hidden" value="O6UJ9A001TB1">
<input class="header-search-box" id="SearchTerm" name="SearchTerm" placeholder="Search Term" type="text" value="">
<input type="submit" class="header-search-input">
Things to try (generally speaking):
Examine your source code (and not what the DOM is interpreting).
The DOM is based on how a browser/HTML parser interpreted the page, and now how it may actually be output. (Invalid markup will generally be suppressed, to the best of the parser's ability, and won't show up in debug tools, but will still sit on the page).
Confirm you don't have any markup mis-aligned.
Razor is smart enough to detect invalid markup, and may be cleansing output (and fixing a potential mistake), but not in a manner you were expecting.
Given this is dynamic content, make sure you're not nesting forms.
Ajax.BeginForm (and the other form helpers) supply <form>/</form> tags regardless; It's in the ctor/de-ctor methods to output those tags.
Some kind of post-processing (on the side of the AJAX processor) may be "cleansing" the output to avoid invalid HTML (e.g nested form tags). If it sees there's already a <form>, it may strip that tag from any supplemental markup being brought in.
You cannot make a form inside another form. Check your parent views to make sure you haven't accidentally started a form, and then included this partial page.
(Thanks for the tip #LiamHT)

Loading a codeigniter view with a form from inside another view

Using codeigniter, I've been trying to load a view inside of a foreach loop, as follows:
$posts = $this->postslibrary->getAllPosts();
foreach($posts as $post){
$home['content'][$i] = $this->load->view('post', $post['data'], true);
$i++;
}
$this->load->view('head');
$this->load->view('home', $home);
$this->load->view('footer');
Each of those post views looks a little like this:
<div class="postnum<?=$post_num?>">
<p>Posted by: <?=$poster_name?></p>
<p>Reply to: <?=$poster_name?></p>
<form>
<input type='text' />
<input type='submit' />
</form>
</div>
And they're being loaded mostly successfully in the 'home' view (which is below for thoroughness).
<div ="posts">
<?php
for($i=0;$i<$count;$i++)
{
echo($content[$i]);
}
?>
<div class="clear"></div>
<a href='/posts/browse/'>Load more items</a>
</div>
But my output ends up looking like:
<div class='posts'>
<div class='postnum1'>
<p>Posted By: Jim</p>
<p>Reply to Jim</p>
<input type='text' />
<input type='submit' />
</div>
</div>
Why are my form tags not coming through?
Check if you already have a form around the current form. Chrome is one of the browsers which doesn't accept this and removes the second form. Using a form in a form is bad practice and I suggest you find a different solution to do the form handling.
Slightly left-of-field answer, but have a look at CodeIgniter Form Generator. I've used it a couple of times and it seems pretty good for generating forms from an array. It's a bit tricky to get your head around it to begin with, but it works well once you've gotten into it.
The basic idea is that you implement a form controller from your ordinary controller, and then just output it in your view file. It might be a more elegant (and sustainable) solution to what you're trying.

Error on submiting form MVC3 .Net

Hi there I have an error when I submit the following form:
<div id="tabs">
<ul>
<li>Project Details</li>
<li>Project Attachments</li>
<li><a href="#Url.Action("Members", "ProjectNetwork", new { IsTab = true })">Project
Network</a></li>
<li>Bulleting Board</li>
<li>Bids Received</li>
</ul>
</div>
<div id="LowerButton">
#Html.Hidden("MainStatus", #Model.Status)
#using (#Html.BeginForm("Dashboard", "Dashboard"))
{
<button type="button" id="MakeComment">
Make a Comment
</button>
<input type="submit" id="GoDashBoard" value="Return to Project List" />
}
</div>
When I press the button "GoDashBoard", The method "Dashboard" in the controller "Dashboard" is not reached. Instead the following error appears:
It tells me that a model property is beign sent to the server. However, there are no model properties inside the dashboard form.. unless I'm sending many forms at the same time. But I dont think thats possible right? Do you guys have any idea of why is trying to set a model property when I'm not actually sending any?
Update:
this is the input of the dashboard action:
public ActionResult Dashboard(int page = 1)
{
var user = (User)Session["User"];
if (user != null)
{...
}}
the input is a default integer. However, I saw the trace of the calls and its submiting another form which is not related to the one im using:
That form is inside of one of the ajax tabs. I dont understand how one form submits another form and they are not nested. Anyone knows a good workaround? because im thinking of receiving both forms in both actions and make some validations.
I solved it by removing the form "Dashboard" and instead adding an invisible link. The button would reference the invisible link:
#*#using (#Html.BeginForm("Dashboard", "Dashboard"))
{ *#
<button type="button" id="MakeComment">
Make a Comment
</button>
<button name="button" type="button" onclick="document.location.href=$('#GoDashBoard').attr('href')">Return to Project List</button>
<a id="GoDashBoard" href="#Url.Action("Dashboard", "Dashboard")" style="display:none;"></a>
#*<input type="submit" id="GoDashBoard" value="Return to Project List" />*#
#* }*#

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?

Resources