I have a model that has several fields and contains a list. I need a view that allows the user to input the Parent fields and then input mutlple child fields. The problem I have is that I don't know how many child objects they are going to add. I need the view to allow them to add as many child objects as they need.
I'm assuming I need a partial view for the child object, but how do I allow them to add the partial view multiple times to the page?
edit
here's what I have so far but it just renders the code in the append method as text on the screen.
$(document).ready(function () {
$("#AddProgramTrainingButton").click(function (e) {
$("#ProgramTraining").append('##{Html.RenderPartial("_ProgramTrainingDetailsCreate",new Online.Models.ProgramTrainingDetailsViewModel());}</br></br>');
e.preventDefault();
});
});
---------2nd edit
I've tried using jquery to load the partial view by calling the partial view in a controller, but this is not working either.
$(document).ready(function () {
$("#AddProgramTrainingButton").click(function (e) {
alert("button clicked!");
$('#ProgramTraining').load('#Url.Action("GetCreatePartialView","PGTController")');
return false;
});
});
// controller method
public ActionResult GetCreatePartialView()
{
return PartialView("_ProgramTrainingDetailsCreate.cshtml",new PGTProgramTrainingDetailsViewModel());
}
i needed to remove the file extention and was missing some closing characters in the jquery
Ronald, take a look to this blog post... I use it and it is perfect.
http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
I got this to work. I wrapped the partial views in a div
$(document).ready(function () {
// This section is to remove a Dynamically added Training section when a button is clicked
$("#RemoveTrainingButton").live('click', function (e) {
e.preventDefault();
$(this).closest('div').remove();
});
// This section adds a Training section to the page when a button is clicked
$("#AddProgramTrainingButton").click(function (e) {
e.preventDefault();
var url = '#Url.Content("~/PGT/GetCreatePartialView")';
$.get(url, null, function (data) {
$('#ProgramTraining').append(data);
}, 'html').error(function (error) {
alert(error);
});
});
});
[HttpGet]
public ActionResult GetCreatePartialView()
{
return PartialView("_ProgramTrainingDetailsCreate",new PGTProgramTrainingDetailsViewModel());
}
I would suggest having an image / button indicating field addition, and then onclick, you can write a simple handler to insert a partial view or any other form field in the form. If you keep the Name of the inserted fields same, then they will be submitted as an array in server, from there you can parse and find out.
You can use jQuery to retrieve your partial view and insert it into the DOM of the main page. Check out the load and ajax functions. You'll need to wire up some sort of control to trigger the asynchronous load. You partial view will be returned from a controller action (different than the full view, e.g. /Controller/MyPageAction and /Controll/MySubformAction where MyPageAction is a full result and MySubformAction is a partial).
You could either rely on an explicit user action (button click), or automatically provide a new set of child fields as soon as the user starts to fill out the last available set of child fields.
Related
I'm developing Single page web application for which I will be using the MVC and knockout. In the _Layout.cshtml, I will have the menu bar using which user can view different views. When I click on the items in menu, I will be calling controller method and being a single page application, I will have to return partial view. However, I'm confused how I can load returned partial view exactly in my view area. If I use Ajax.BeginForm, I can specify the UpdateTargetID in which I need to update my partial view but as with menu item click, it will just be server method call. So I wonder how I can update the partial view inside view area?
Do you think writing following javascript function for each menu items is what I need to do?
$('#menuitemId').click( function() {
$.ajax({
type: 'POST',
url: '#Url.Content("~/ControllerName/ActionName")',
data: objectToPass,
success: function (data) {
$('#divid').innerHTML = data; // data is partial view returned from controller
}
});
}
Also, can someone point me/share working demo/good documents of Single page web application with MVC and knockout?
That looks fine to me.
You could also make it simpler like this:
$('#menuitemId').click( function() {
$('#divid').load('#Url.Content("~/ControllerName/ActionName")' + menuItemId);
});
I am using MVC3, C#, Razor, EF4.1, SQLServer 2008.
I have a parent form with a dropdown for "Suppliers". I wish to add a "quick add" link/button that enables the user to quickly add a supplier to the DB which is then available in the dropdown for selection. At present this is achieved by
Parent Page -> Add Supplier Page -> Parent Page(Page Refresh)
Of course on return to the parent page, it refreshes and removes all non saved data - which is a problem. It would be better to have a popup window which then saves the suppliers and then just refreshes the dropdown portion of the parent page form. So I believe I am seeking an approach to:
Parent Page -> Popup(Modal) -> DB Save -> Refresh DropDown in Parent Page (Ajax???) -> close Modal popup.
I would appreciate guidance on the above, as I am a little stuck on the best practice and hopefully simple approach to this.
Many thanks.
I normally do something like this:
Create an 'Add' button that will display a popup. (I use jQuery dialogs. They are simple, free, and easily to implement by just calling .dialog on a div). Inside this dialog have the appropriate fields needed to create a new supplier. Have a 'Save' button in this dialog and have it wired up to a AJAX post. (Again this is very simple using jQuery)
If you do use jQuery its as simple as submitting that form to your controller action that will then call you data access layer to save the new supplier entity. When the AJAX call comes back successfully you can reload the contents of the supplier grid with another AJAX post. All the 'Magic' comes from implementing AJAX really which will allow for you to retain the users input and not reload the whole page. The AJAX call that is executed after the user enters in a new Supplier and clicks save would look something like this:
In your JavaScript:
$.ajax({
url: "ControllerName/SaveNewSupplier",
Data: $('#YourAddNewSupplierFormName').serialize(),
Type: "POST"
Success: function(result) {
// this is what will get called after a successful save and return of your action method on your controller. This is where you will put the call to repopulate the supplier list with the updated list.
UpdateSupplierList(); // This function is created below
}
});
In your controller:
Public JsonResult SaveNewSupplier (NewSupplierModel newSupplier)
{
// save your new supplier through your data access layer
// if save is successful then return
Return Json({success = true}, JsonRequestBehavior.AllowGet)
}
Then to repopulate the initial div that contains all the suppliers do something like this:
In JavaScript:
function UpdateSupplierList()
{
$.ajax({
url: "ControllerName/GetAllSuppliers",
Type: "GET"
Success: function(result) {
$('#SuppliersDiv').html(result.suppliers)
}
And in your controller:
// remember that a lot of this is pseudo code and your will have to implement it better for your situation. But basically its just:
Public JsonResult GetAllSuppliers()
{
var suppliers = db.GetSuppliers()
return Jason({suppliers = suppliers}, JsonRequestBehavior.AllowGet);
}
EDIT: If you are updating a SelectList via jQuery then this article is almost identical to what I explained but goes into much more detail on updating the select list. Hope this helps.
http://www.joe-stevens.com/2010/02/23/populate-a-select-dropdown-list-using-jquery-and-ajax/
Following is my view which contains a div in which partial views are rendered based on actions performed in the view.
//Boiler Plate HTML
<div id="PartialViewHolder">
#Html.Partial(Model.PartialView, Model)
</div>
//Boiler Plate HTML
The partial views are rendered via an ajax call which is as follows
//The url is supplied based on some actions in the main view
function AjaxCall(url){
$.ajax({
url: url,
cache: false,
success: function (html) {
$("#PartialViewHolder").empty();
$("#PartialViewHolder").html(html);
},
error: function (result) {
alert("Error: " + result.status + ": " + result.statusText);
}
});
}
The main page also loads a few other scripts which are common to the partial views. These scripts work when the page is first rendered, i.e when the default partial view is rendered. However these scripts stop working for partial views which are loaded by the ajax call. I believe that these scripts need to be reloaded when the DOM elements change. I am looking for a clean way to reload those scripts when the partial view div is reloaded.
You need to do a bit of reading about Event binding. http://api.jquery.com/on/
Tricky to understand at first but worth it once you do.
Assuming you've got some code like this.
<div class="container">
<div class="partial">
Click here to do stuff
</div>
</div>
JS Code like the example below will only work for objects present when you do the binding (usually document.ready()) It seems like this is the situation you are describing.
$(".magic-link").click(function(){
alert("Magic link clicked");
return false;
})
If you want the event to fire on objects that haven't yet been loaded onto the page then you need to bind an event handler to the container div i.e. the bit which doesn't change.
Like this
$(".container").on("click", ".magic-link", function(){
alert("Magic link clicked");
return false;
});
The event bubbles up to the event handler and fires the event. This has another advantage that one event handler and potentially handle events from hundreds of objects.
As a guideline try to bind the listener to the nearest parent object that will not change. In the case of the example this is the Container div. This keeps the bubbling to a minimum.
I'm new to Asp MVC, and I'm trying to accomplish a little async update (I'm using MVC3 RC2, with Razor, but I can manage with ASPX solutions too).
I have a Master page, which renders a shopping cart box on every page by calling Html.RenderAction("Cart","Shop"). The Cart action of the ShopController calls the database, etc, and outputs the results. This works.
First problem: if I put an ActionLink in this partial view (like Html.ActionLink("Remove")), then even if I call PartialView() from the Remove action, it renders only the shopping cart, and nothing else (in essence, my page disappears).
Second problem: There is a div called "cartContent" inside this partial view. I want to be able to put a link ANYWHERE (not just on the Master page or in the partial view), which when pressed calls a controller Action, and then updates ONLY the cartContent div based on the results. I've tried Ajax.ActionLink but it does the same as Html.ActionLink, even though I imported the Microsoft.MvcAjax js libs.
Also, if I solve the first problem, I want that to be async as well.
What solution do I use? I've tried setting UpdateTargetID to "cartContent", I've tried wrapping the cartContent into an Ajax.BeginForm, nothing. Do I HAVE to use jQuery (which I know nothing of)? Do I serialize some response to JSON, and update the div manually in Javascript? (I'm not really good at JS, I'm coming from the C# side of things)
You put a link wherever you want:
#Html.ActionLink("remove item", "remove", "somecontroller",
new { id = Model.Id }, new { #class = "remove" })
And then in a separate javascript file:
$(function() {
$('.remove').click(function() {
// when the link is clicked
// perform an ajax request:
$.ajax({
url: this.href,
type: 'delete',
success: function(result) {
// when the AJAX call succeed do something with the result
// for example if the controller action returned a partial
// then you could show this partial in some div
$('#someDivId').html(result);
}
});
// don't forget to cancel the default action by returning false
return false;
});
});
Remark: if the div you are updating contains also the link then you might need to use the .live() function or the click event handler will not work the second time because the DOM will be modified:
$('.remove').live('click', function() {
...
});
I have this weird thing happening.
I have a PartialView with 3 fields on it. I do a jQuery ajax post to my action result and if the model passes validation i save the record. I also then set the model to empty and pass it back to the view as a partial view.
public ActionResult jQueryAddComment(Comment comment)
{
if (ModelState.IsValid)
{
//do stuff here
comment = new Comment();
}
return PartialView("AddNewComment", comment);
}
When I get back to the page my JS replaces the contents of the comments div with the html from the new partial view.
function submitComment() {
$.post('/Home/jQueryAddComment', { forumItemId: $('#id').val(), owner: $('#owner').val(), text: tinyMCE.get('text').getContent(), emailAddress: $('#emailAddress').val() }, function (result) {
alert(result);
$('.AddNewComment').html(result);
});
}
However, when the page renders the values are back in place. I can see that an empty model is being passed to the view so why are my previous values still there?
Even the alert shows the values in place even though I'm passing an empty object to the partial view in the controller.
edit
I should mention that I can't clear the fields within the JS of the page as I want to use the same code to render errors as well as successful requests.
Use ModelState.Clear() before returning the new blank model as a partial view, like:
if (ModelState.IsValid)
{
//your save logic
ModelState.Clear();
comment = new Comment();
}
return PartialView("AddNewComment", comment);
The standard HTML helpers look into ModelState and ViewData for values before using the values you passed to the helper.
This may help:
How to clear textboxes defined with MVC HTML helpers