Conditionally Pass Data from Enclosing View to Partial View - javascript

My Requirement
I need to render a partial view on selection of a dropdownlist
On page load (from Controller) I have all the required data(viewmodel) for the Partial View
All the partial views need to get the same data from the viewmodel of the View(cshtml)
On selection of the dropdown list value, the required Partial View(given below 1- 4) needs to be rendered.
Rendering Partial View 1
#{
Html.RenderPartial("_Dashboard", new Dashboard.Web.Models.SignalDataViewModel { dData = Model.dData });
}
Rendering Partial View 2
#{
Html.RenderPartial("_Dashboard_Graph", new Dashboard.Web.Models.SignalDataViewModel { dData = Model.dData });
}
Rendering Partial View 3
#{
Html.RenderPartial("_Dashboard_Arrow", new Dashboard.Web.Models.SignalDataViewModel { dData = Model.dData });
}
Rendering Partial View 4
#{
Html.RenderPartial("_Dashboard_Custom", new Dashboard.Web.Models.SignalDataViewModel { dData = Model.dData });
}
My Query
Please suggest how should I conditionally render partial view(from among a list of Partial Views with same ViewModel) as per the selection of dropdown list while having the data for the partial views that's already availble within the View's(cshtml-parent) ViewModel

Inside of doing all of this via html. I would suggest using javascript.
Have a single div that has an ID such as
<div id="InterchangableView"></div>
Add an onChange event to the dropdown and pass a javascript function the value of the dropdown
In the function determine what value it is and call the necessary controller method such as below
if(id == 1)
{
var json = '{controllerParam: ' + id + '}';
$.ajax({
url:'#Url.Action("Action", "Controller")',
type:'POST',
data: json,
contentType:'Application/json',
success:fucntion(result){
$("#InterchangableView").html(result);
}
});
}
In the controller action, depending on the result passed into it, do a check and return the correct partialView this way.
Every time the dropdown changes, the javascript should get called, which should return a partialView which should overwrite whatever is in the div that that Id is located against.

I finally did some work around to implement this.
In the JavaScript on selection of drop-down, via ajax call I passed the model data to a controller returning Partial View.
In the Controller, the right partial view is decided and it returned back that partial view as html data to my ajax call that I use to be replace within the required(partial view) div.

Related

Pass hidden model data to the controller using ajax in mvc

Once again stumped on a partial view issue using ajax to swap out partial views.
I have a partial view that is loaded onto a page when the page is loaded. This partial view has a button on it that when clicked, will replace that partial view with another partial view. Previously I was accomplishing this with #Ajax.ActionLink and passing in the page's Model as a parameter to be passed to the controller. This was working correctly.
However, the next step was to fill in a form on the new partial view and submit it which would return another partial view. I asked how to do that on here and got it to work using jquery event delegation.
Now I'm trying to replace the #Ajax.ActionLink with a $.ajax function and am running into an issue with my js script where the model data already in the view or partial view is not being passed to the controller by the js.
Here's what I mean:
I have a page called ReviewPage that on load, will call an action that returns a partial view. This partial view is determined based on a value from the page's model that is passed to the controller. More often than not, the view returned is _NoNotes:
#model GuestPointerAppV4.Models.ViewModels.NotesOnCompanyViewModel
<div id="no_company_notes">
<h4>Notes on Company</h4>
<div class="row col-sm-6 col-sm-offset-6">
<div class="text-center">
#Html.HiddenFor(item => Model.RequestId)
<div class="primary-action-bttn-border">
<div class="primary-action-bttn-bkg">
<button data-gp-ajax="true" data-gp-target="#no_company_notes" value="Save" action="#Url.Action("_CompanyNotesEditGet", "NewSignUpRequestReview")" method="get" class="btn btn-default primary-action-bttn">
Add Note
</button>
#*#Ajax.ActionLink("Add Note", "_CompanyNotesEditGet", Model, new AjaxOptions { UpdateTargetId = "company_notes", InsertionMode = InsertionMode.Replace, HttpMethod = "GET" }, new { #class = "btn btn-default primary-action-bttn" })*#
</div>
</div>
</div>
</div>
<div class="row text-center padding-25-top">
<p>There are no notes for this company. Do you want to add some?</p>
</div>
</div>
You'll notice the commented out ajax action link in the code above. This was how I was previously able to get the model passed to the controller.
When the button is clicked on this partial view, the following js responds:
$(document).on('click', 'button[data-gp-ajax="true"]', function () {
var $form = $(this);
var options = {
url: $form.attr("action"),
type: $form.attr("method"),
data: $form.serialize()
};
$.ajax(options).done (function (data) {
var $target = $($form.attr("data-gp-target"));
$target.replaceWith(data);
});
return false;
});
I want to reuse this js as much as possible so I utilize custom data- attributes to help call the right function (data-gp-ajax="true") and tell the script where to return the results (data-gp-target="#targetid").
The problem is that in debugging this, I found that while Model.RequestId is not 0 on the page, this value is not getting picked up by the js and passed to the controller. So, when my controller looks for the data it doesn't find it and returns a null or 0 depending on the type of data I'm trying to pass.
I did a bit of research and tried to encode the Model in the partial view itself using the following at the top of the partial view's code just after the model typing:
#{
var val = Json.Encode(Model);
}
<script type="text/javascript">
var model1 = #Html.Raw(val)
</script>
Then, in my js function, I tried passing model1 to the controller by using it like so:
$(document).on('click', 'button[data-gp-ajax="true"]', function () {
var $form = $(this);
var $model = $(model1);
var options = {
url: $form.attr("action"),
type: $form.attr("method"),
data: $model.serialize()
};
$.ajax(options).done (function (data) {
var $target = $($form.attr("data-gp-target"));
$target.replaceWith(data);
});
return false;
});
I also tried data: $model and data: $model.first() but no such luck. I managed to debug and see the data I was expecting to see in the js on the $model variable so I know it's getting in there but it isn't getting passed to my controller when it's called.
Really what I'm looking for is a clean and reliable way way to pass the Model for the page into the JavaScript and have it pass it along to the Controller to execute some action on before a partial view is returned to replace the original partial view.
Thoughts?
Update
Here is an example of the controller:
[HttpGet]
public ActionResult _CompanyNotesEditGet(NotesOnCompanyViewModel notesOnCompanyViewModel)
{
//Some actions are taken on the model passed in and then repopulated to notesOnCompanyViewModel
return PartialView("~/Views/NotesOnCompany/_CompanyNotesEdit.cshtml", notesOnCompanyViewModel);
}
However, when I debug and the action is called by $.ajax, the notesOnCompanyViewModel is blank. Even when I can see there is data that should be getting passed by the js function.
All you need is to send the unique Id. for that, you can simply override the button click event and make an ajax call with the Id in the request url. If you would like to take advantage of the Url helper method to generate the correct relative path to the action method, you can do that and set the result of that to html5 data attribute on the button.
<button id="addNote"
data-url="#Url.Action("_CompanyNotesEditGet", "NewSignUpRequestReview",
new { id=Model.RequestId})" >
Add Note
</button>
Assuming your _CompanyNotesEditGet action method accepts this Id and return the value as needed
public ActionResult _CompanyNotesEditGet(int id)
{
var vm= new NotesOnCompanyViewModel { RequestId=id };
//load other properties of vm as needed.
return PartialView(""~/Views/NotesOnCompany/_CompanyNotesEdit.cshtml",vm);
}
And the script to ajaxify the click event. You can use the load method to make the ajax call and update the DOM element.
$(function(){
$(document).on("click","#addNote",function(e){
e.preventDefault();
var url=$(this).data("url");
$("#no_company_notes").load(url);
});
});
If you are editing a note, Inside your action method, you can read your note entity from the db using the Id passed in.
This should work assuming you have no script errors in the page.

Getting parameters from query string

I am creating a web page using ASP.Net WebAPi, MVC and Knockout.
I have a normal MVC controller that loads the pages when I need them:
[Authorize]
public class AdminController : Controller
{
public ActionResult Clients()
{
return View();
}
public ActionResult ClientEdit(int? Id)
{
return View();
}
}
And once the page is loaded, my Knockout model takes care of the loading of the data. So, the 'Clients' controller simply loads a list of all clients. When on that screen, a user can click 'Edit' next to a client, and the page is navigated to the 'ClientEdit' controller, which takes an id.
So, my knockout click event looks like this in my knockout view model:
self.EditClick = function () {
if (this.ClientId && typeof this.ClientId !== 'undefined') {
window.location.href = "/Admin/ClientEdit/" + this.ClientId;
}
else
window.location.href = "/Admin/ClientEdit/";
}
(It handles the 'Create New' button and the edit button, hence the 'if')
Once I redirect, the MVC controller loads the page, and the URL is:
http://localhost:49389/Admin/ClientEdit/1
I then load the knockout model, and would like to make an API call to get the data...
After my page loads, I want to bind the view model to the page. Here's my view model at the moment:
function AdminClientEditor() {
var self = this;
self.Name = ko.observable("");
self.ContactName = ko.observable("");
ko.applyBindings(new AdminClientEditor(), $("#clienteditor")[0]);
So, I will create a $.get method that calls a webAPI method that will return me data based on the id. I just need to get the ID somehow.
But, how do I get the Id (In this case, '1', from the URL?
And, is this the right way to achieve what I am trying to do?
You can pass the id value to view via viewbag.
public ActionResult ClientEdit(int? Id)
{
ViewBag.ClientId=id;
return View();
}
and in the view's script section
var clientId="#ViewBag.ClientId";
alert(clientId);
// use this
If your javascript code which accesses this id value is inside a separate external js file, you may set this value to a js variable in your view and access it in your js file. Make sure to use namespacing to avoid global variable overwriting value issues.
So in your view
<script>
var myApp = myApp || {};
myApp.ClientId= "#ViewBag.ClientId";
</script>
<script src="~/Scripts/PageSpecificExternalJsFile.js"></script>
And in the PageSpecificExternalJsFile.js file,
var clientId=myApp.ClientId;
//use this as needed
I'm not sure if this is the best way, but you can get the ID from the URL by using JS:
var id = GetID();
function GetID() {
var href = location.href;
var results = href.split("/");
return results[results.length - 1];
}
I've come up with this solution which works, but I am unsure if it's the best way. It seems pretty good.
I created a MVC ViewModel class in my application code, called 'GenericParameteModel', which at the moment, has a single parameter, "Id".
I then modified my page loading MVC method:
public ActionResult ClientEdit(int? Id)
{
var mv = new GenericParameteModel { Id = Id };
return View(mv);
}
On my View page, I added the model 'GenericParameteModel' to the View.
I created a hidden field, called 'ClientId' on the view.
<input type="hidden" id="clientId" value="#model.Id">
Then, within my knockout view model, I check if $("#clientId").val() has a value. If so, I do the $.get call, using that value, and populate my view model.
In doing so, all my initial page loads from MVC will have the ability to you the GenericParameteModel, and it will be a pattern for other pages. As it's a model, I can add new fields as my application requires.
This seems to work well. I'm unsure if this is an acceptable way as I am new to this (MVC to load views and the Knockout/WebApi to get the data after loading). But it seems neat and manageable.

asp.net mvc passing any data from a partial view that is rendered with $.get() to ContentPage

I am trying to make my web application like a desktop application.
I am also not using any _LayoutPage and #RenderBody().
I have a ContentPage as MasterPage and a tag named main
I am using ajax get method to render my views or partial views like this:
$.get(url).done(function (result) {
$("main").html(result);
});
I managed to inject my script and css files with javascript functions.
And now I want to pass some specific datas without using javascript functions.
It can be via using ViewBag, I guess.
I want to pass that data from my partialView:
ViewBag.BodyClass = "signup-page";
to my MainPage like this:
<body class="#ViewBag.BodyClass">
How can I do that?
A little note: Please ignore that I am a newbie and my low reputation
If you have a script manager ($.get) that calls your server to get the views and partial views, no problem.
When you request a URL, normally MVC calls a Controller and Action. In that action you can return content, view, partial view, file and so on...
You can create a new instance of a class model and pass to your partial view.
public ActionResult Index(string parameter1, string parameter2)
{
var model = new Models.ModelTest();
model.BodyClass = "some class";
return PartialView("_Page", model);
}
You will call some like this:
$.get("http://localhost/app/getviews?id=3422&parameter1=test&parameter2=foo")
In your view or partial view:
#model YourApp.Models.ModelTest
<body class="#Model.BodyClass">
I use that all the time.
I wrote that code on my partialView. It adds a class at ContentPage's body tag
$("body").addClass("signup-page");

Ajax - How to provide data to a child JSP via a parent JSP and reload?

I'm hoping someone can help me figure out the best way to address my issue. What I'm trying to do is utilize an existing JSP partial (child) into another JSP page (parent). (These pages are driven by Java Controller classes in a Weblogic 12c environment using Spring.) The child JSP contains a data table that is built off of a list supplied by its current Java Controller. (The model attribute is called claimList.) The first thing I tried doing was including the child into the parent this way:
<jsp:include page="../../jsp/claimSummary.jsp"/>
In the parent JSP, there is an included JS file that contains a function that builds the same exact data that the claimList attribute for the child JSP needs. This method is executed on load.
Included JS file for parent JSP:
function parent() {};
var claimList = [];
$(function() {
parent.buildClaimList();
};
parent.prototype.buildClaimList = function() {
var fileNumber = $("#sidebar_primary_fileNumber").text();
//request all the claims
$.ajax({
url: contextPath + "/getClaimList",
type: "POST",
data: {fileNumber: fileNumber},
dataType: 'json',
success: function (claims) {
if (claims.success) {
if (claims.data.length > 0) {
// Sort by claim date.
claims.data.sort(function (a, b) {
return new Date(a.claimDateDt) < new Date(b.claimDateDt);
});
claimList = claims.data;
}
}
}
});
$('#claim-summary-table').load("../../../WEB-INF/jsp/claimSummary.jsp", function() {});
return true;
};
I tried making the list available by making the claimList local variable in the parent JS file... that didn't translate to the child JSP, not surprisingly. Also, at the end of the buildClaimList function, I am attempting to reload the child JSP with the updated claimList data, which also isn't working, but I don't know why.
So, the child JSP does not reload, and the data table is never populated with data. I was trying to make the least amount of changes possible to get this child JSP to work in the parent, by changing mainly the parent JSP and/or JS file. Is there any way I can get the local variable claimList to be recognized by the child JSP the same as it would have access to the claimList attribute from the controller model? And what would be the best method to refresh that JSP to get it to show the data gathered from the Ajax call without reloading the parent page?
Thanks for your help!
Compose the data claimList into an html table data and fill the data in the table.
var tableData = {some processing of claimList}
Now use this tableData variable and update $('#claim-summary-table')
$('#claim-summary-table').html(tableData);

Return View from controller after jquery post

Hi I am new to MVC and I have the below senario
VIEW:
step3.cshtml is my view
This has data binded to step3.js(using knockout)
$.post("/Step/Step4", { "some":some_data }, function (data) {
}, 'JSON');
CONTROLLER:
[HttpPost]
public ActionResult Step4(model foo)
{
//save this data to the database and return a view
using (DBContext dbContext = new DBContext())
{
dbContext.Table.Add(foo);
dbContext.SaveChanges();
}
return View(foo);
}
public ActionResult Step4()
{
//get this view with the model
}
I am able to see that the view Step4.cshtml is able get the property values from model but.
I see that my View Step4.cshtml is a response header from the post how do I render this in the browser.
Is this the right approach??
So is it that an HTML form post can return a view and replace the whole content and AJAX cannot do that except for the partial view update?
When you call $.post, you are making a jQuery ajax request with a POST method. That data is given back to you in the success method. If you are returning the view, then you will have to manually replace the html in your document with that response.
Normally, when you use ajax like this, you would return a PartialView to update a section of your page, not your whole page. You might want to see if you can return a partial and update a div.
You can also do that by using an Ajax.ActionLink, and in the AjaxOptions, specify the id of the element you want to update when the response is returned, and the InsertionMode, which should be set to Replace. And you won't have to worry about replacing the content yourself.
Please see this stackoverflow question, which may help you: How To Use Ajax.ActionLink

Categories

Resources