How to update a View without Postback in MVC3 - c#

How can I update a dropdownlist in MVC3. I want to refill it with latest data filled by some other view, but I do not want to postback the view and want to achieve it with jquery.
I have a dropdownlist like:
#Html.DropDownListFor(m => m.Department, Model.Departments)
#Html.ValidationMessageFor(m => m.Departments)
<input type="button" value="Refresh" id="btnrefresh" />
I have written jquery code to call controller's method:
$("#btnrefresh").click(function () {
var ref = '#Url.Action("RefreshDepartments")';
var model = '#Model.ToJson()';
var data = { empModel: model };
$.getJSON(ref, data, function (result) { alert(result.message); });
return false;
});
And Here is the controller method:
public ActionResult RefreshDepartments(EmployeeModel empModel)
{
empModel.Departments = GetDepartments();
empModel.Roles = GetRoles();
return Json(new { message = "Updated successfully"}, JsonRequestBehavior.AllowGet);
}
How can I update the dropdownlist with latest values on clicking "Refresh" button without any postback?
Is it a good idea to pass the model to the controller and update the model properties? What other ways are possible ?

It doesn't look to me like you need the model to be posted to your controller for what you're doing. In addition, yes, you absolutely can do this with jquery! On a side note, you could also do it with an Ajax.BeginForm() helper method, but lets deal with your jquery example.
Rather than complexify your jquery with your #Url.Action, you can simply call the path itself.
$("#btnrefresh").click(function () {
var ref = 'ControllerName/RefreshDepartments';
$.each(result, function (index, val) {
$('#whateverYourRenderedDropdownListHtmlObjectis')
.append($("<option></option>")
.attr("value", val.Text)
.text(val.Text));
});
});
Now, for your controller...
public JsonResult RefreshDepartments()
{
return Json(GetDepartments, JsonRequestBehavior.AllowGet);
}
private SelectList GetDepartments
{
var deparments = GetDepartments;
SelectList list = new SelectList(departments);
return list;
}
This is an alternative to returning the model. It allows you to manipulate the raw JSON instead. Hope it helps!

You almost did it all! Why don't you send the data, I mean list, by RefreshDepartments action? You sent a message to view, so you can send the list similarly and instead of alerting the result you can fill the dropdownlist. something like this:
public ActionResult RefreshDepartments(EmployeeModel empModel)
{
return Json(new { departments = GetDepartments()}, JsonRequestBehavior.AllowGet);
}
$.getJSON(ref, data, function (result) {
$("#Department").html("");
for (var i = 0; i < result.departments.length; i++) {
var item = result.departments[i];
$("#Department").append(
$("<option></option>").val(item.Id).html(item.Name);
);
});
});

Related

Need to persist value selected in dropdownlist in MVC View Using Angular

I am new to both MVC and AngularJs so please excuse me if this is a stupid question. I have a dropdownlist in an Asp.net MVC View that is populated using AngularJs. When the user selects a Company in the dropdown list, I use the companyId to populate an unordered list. My problem, I need to use that same selected CompanyID in another controller and C# method. I have found some info on saving data in a service to reuse it, but I'm not sure if that is what I really need here (or if there is a simpler way to do it than creating a service), but if it is, I don't know how to save the value in a service.
Here is my View code:
{{company.vchCompanyName}}
Current Dashboard Modules:
{{m.vchRankingWidgetModuleHeaderText}}
Here is my Angular Controller code:
myApp.controller("CompanyController",
function($scope, $timeout, companyService)
{
getCompanies();
function getCompanies() {
companyService.getCompanies()
.success(function (data) {
$scope.companies = data;
})
.error(function (error) {
$scope.status = 'Unable to load customer data: ' + error.message;
});
};
$scope.getCurrentModules = function(){
companyId = $scope.company;
companyService.getCurrentModules(companyId)
.success(function (newdata){
$scope.currentModules = newdata;
});
}
});
Here is my Angular Service:
angular.module('dashboardManagement')
.service('companyService', ['$http', function ($http) {
this.getCompanies = function () {
return $http.get('/Home/GetAllCompanies');
};
this.getCurrentModules = function (id) {
return $http.get('/Home/GetCurrentModules?companyId=' + id);
};
}
]);
Any assistance is greatly appreciated!
I tried using the Service but I cannot get it to work. I need to show Business Units for a company if the Business Units checkbox is checked. I put the function "getBusinessUnits" on the ng-checked and tried to use the service to retrieve the CompanyID. My View looks like this:
<div ng-controller="BusinessUnitsController">
<input id="ckBusinessUnit" type="checkbox" ng-checked="getBusinessUnits()"/>Exclude by Business Units<br />
<ul>
<li ng-repeat="unit in businessUnits">{{unit.Description}}</li>
</ul>
</div>
My Controller looks like this:
myApp.controller("BusinessUnitsController",
function ($scope, $timeout, companyService) {
$scope.getBusinessUnits = function () {
companyId = companyService.selectedCompanyId;
companyService.getBusinessUnits(companyId)
.success(function (data) {
$scope.businessUnits = data;
});
};
});
The code in the Service is exactly as you suggested:
angular.module('dashboardManagement')
.service('companyService', [
'$http', function ($http) {
this.selectedCompanyId = null;
this.getCompanies = function () {
return $http.get('/Home/GetAllCompanies');
};
this.getCurrentModules = function (companyId) {
this.selectedCompanyId = companyId;
return $http.get('/Home/GetCurrentModules?companyId=' + companyId);
};
this.getBusinessUnits = function (companyId) {
return $http.get('/Home/GetBusinessUnits?companyId=' + companyId);
}
}
]);
I'm obviously missing something.
The CompanyService can be used to stock a selectedCompanyId as a property.
angular.module('dashboardManagement')
.service('companyService', ['$http', function ($http) {
this.selectedCompanyId = null;
this.getCompanies = function () {
return $http.get('/Home/GetAllCompanies');
};
this.getCurrentModules = function (companyId) {
this.selectedCompanyId = companyId;
return $http.get('/Home/GetCurrentModules?companyId=' + companyId);
};
}]);
Then you can access the selectedCompanyId everywhere in your others controller/directive by injecting companyService.
Note that it is like a Singleton with a single instance, so you can have only one selected company for your whole angular application.
if I understand well you need to save the select companyId in your View and then pass it to your controller(c#) right?
try this, add a new property in your angularjs controller
$scope.SelectedCompanyId = '';
then in your dropdownlist add this attribute
ng-model="SelectedCompanyId"
then add a new hidden input
<input type="hidden" name="CompanyId" value="{{SelectedCompanyId}}" />
now if in the model that are you using in your view have a property CompanyId, when you do the post back it will map the value, or just in your controller add a new parameter
[HttpPost]
public ActionResult YourActionName(YourModel model, int? CompanyId)
{
//you can access to the CompanyId
//int? CompanyId --> this is only if your model doesn't have a property called CompanyId
}

How to get value from Javascript popup call in MVC ActionResult ?

I have a javascript function that calls a MVC action result which in turn will populate the correct View. I need to pass .Net code with that pop up call, is it possible?
So for example I need to pass a integer from the model over so I can use it in my action result.
a button click calls this function
ShowPopUp = function () {
window.showModalDialog("/FileUpload/GetPopupData", "wndPopUp", "width=300,height=500");
}
and here is the action result
public ActionResult GetPopupData()
{
//Call the pop up view and populate it accordingly
return new GetDocumentTypeAction<ActionResult>
{
OnLoaded = m => View("../../Areas/Exports/Views/FileUpload/FileUpload", m),
OnErrorOccured = (m) => Redirects.ToErrorPage()
}.Execute(GtsClient);
}
How will I send the int over and how will I read it in the action result?
In your view, render out the integer you want from the model as a JavaScript variable that you can reference in your ShowPopUp() function.
<script>
var viewId = <%=Model.ViewId%>;
ShowPopUp = function () {
window.showModalDialog("/FileUpload/GetPopupData/" + viewId,
"wndPopUp", "width=300,height=500");
}
</script>

How to replace div's content by partial view or update it's content depending on what json result returns on ajax complete?

Well I have simple ajax form:
This is MyPartialView
#using(Ajax.BeginForm("action", "controller", new AjaxOptions
{
OnBegin = "beginRequest",
OnComplete = "completeRequest",
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "div-to-replace"
}, }))
{
<input type="text" id="my-input" />
...
}
This is parent view:
<div id="div-to-replace">
#Html.RenderPartial("MyPartialView")
</div>
In my controller I have:
[HttpPost]
public ActionResult action(Model model)
{
if (ModelState.IsValid)
{
// do staff with model
// return partial view
return PartialView("MyPartialView");
}
// else add error and return json result
return Json(new {error = "invalid data"});
}
And my javascript on ajax complete method:
function completeRequest(data) {
var result = $.parseJSON(data.responseText);
if (result != 'undefined' && result != null && result.error) {
// just display error and not replace all content
// attachModelError is my custom method, it just adds vlaidation-error class to inputs, etc.
attachModelError("my-input", result.error);
return;
}
// or show returned html (depending on returned model form inputs will be modified:
// select box with different items in my case
$('#div-to-replace').html(data.responseText);
}
But the problem is I have empty #div-to-replace if model state is invalid. If model state is ok every thing works fine. If I use different insertion mode it creates duplicates of div's content before or after div.
Summary:
I want different InsertionMode behavior depending on json result. I don't need replace data if (result != 'undefined' && result != null && result.error).
I had to solve this problem once so very long ago. I came up with a simple solution, which today, may not be the best solution but it gets the job done.
My solution involved setting up a controller action that would render just the partial with data that it would need and have my JavaScript request it.
C#
MyController: Controller
{
public ActionResult GetPartialViewAction()
{
return PartialView("mypartialview", new partialViewModel());
}
}
JavaScript
$.ajax({
url: "/my/getpartialaction/"
}).done(function(data) {
$("#partialViewDiv").html(data);
});
HTML
<div id="partialViewDiv"></div>
A better solution would be to use a MVVM/MVC JavaScript library that would allow you to leverage html templates and only have to transmit the data over your ajax solution. I recommend looking into knockout.js or backbone.js for this more accepted pattern.
I have the same problem with the default c# ajax forms. I have a solution what might work.
jQuery:
$(function () {
var ajaxFormSubmit = function () {
var $form = $(this);
var options = {
url: $form.attr("action"),
type: $form.attr("method"),
data: $form.serialize(),
cache: false
}
$.ajax(options).done(function (data) {
data.replaces.each(function (replace) {
$(replace.id).replaceWith(replace.html);
});
});
return false;
};
$("form[data-ajax='true']").submit(ajaxFormSubmit);});
form.cshtml
#using (Html.BeginForm("Create", "Menu", FormMethod.Post, new { data_ajax = "true" }))
{}
model sample
public string Id {get;set;}
public string Html {get;set;}
The last thing you need to do in your controller is return a json result with a list of your model sample, id is target element to update, for the html you must use a render partial / or view as string.
For render view to partial see [question]: https://stackoverflow.com/questions/434453

Passing list of items from Controller/Model to a variable in javascript - autocomplete

I've a method in a NamesModel which fetches all the names and returns a list of names:
public static List<NamesModel> GetAllNames()
{
List<NamesModel> names = new List<NamesModel>();
//
// code to fetch records
//
return names;
}
In my controller:
public ActionResult Index()
{
NamesModel model = new NamesModel();
model.GetAllNames();
return View(model);
}
In the view, I've got a textbox:
#Html.TextBox("search-name")
Now in my javascript, I want to fetch all names into a variable either from a model (from method) or from controller, for example:
<script type="text/javascript">
$(function () {
var names = ...........
$(document).ready(function () {
$('#search-name').autocomplete({
source: names
});
});
});
</script>
If I use hardcoding then it works but I want to use the names stored in the db. Is it possible?
hardcoding example:
var names = ["abc", "xyz"];
You could use Ajax and Json for this
For your controller:
[HttpPost]
public JsonResult GetAllNames()
{
List<NamesModel> names = new List<NamesModel>();
//
// code to fetch records
//
return Json(names);
}
Or for debugging so you can view the json in browser:
public JsonResult GetAllNames()
{
List<NamesModel> names = new List<NamesModel>();
//
// code to fetch records
//
var result = Json(names);
result .JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return result ;
}
(note this is actually jquery but since you use document.ready you've allready included jquery)
in your javascript make a call to the method above:
$.getJSON(#Url.Content("~/ControllerName/GetAllNames/"), function (result) {
var ListWithNames = data;
});
The "source" options property can be a string wich points to the URL which return json data (http://api.jqueryui.com/autocomplete/#option-source)
The best solution to my problem is in this blog: http://theycallmemrjames.blogspot.co.uk/2010/03/jquery-autocomplete-with-aspnet-mvc.html
Thanks to everyone who tried to help me.

How to postback to a controller function when a value is selected from dropdown

I have created a dropdownlist on the view and showing a list.
#Html.DropDownListFor(m => m.SelectedId, new SelectList(Model.List, "ID", "Name"))
I want to refresh the page when the user selects the value from the drop down.
I don't know how to map the selection event from dropdown to a controller function without clicking any button.
On the view load there is a controller function which is populating the view with the list.
public ActionResult Populate()
{
List<string> list = get it from sql server
ViewModel viewModel = new ViewModel();
viewModel.list = list;
return view();
}
But how do you call a controller function which will take the selected value as an Id and retrieves the data and refreshes the page with the result.
You can't do it without javascript help. Just bind on select event and send the form or make an ajax request.
using jQuery:
$('#yourDropDownId').change(function(){
$('#yourFormId').submit();
});
or if you need ajax call insted of submit use $.post or $.get.
Add this to your layout in the head:
<script type="text/javascript">
$(document).ready(function () {
$('select:[autopostback=true],input[type=checkbox]:[autopostback=true],input[type=radio]:[autopostback=true]').live('change',function () {
$(this).closest('form').submit();
});
});
</script>
in your view:
#using (Html.BeginForm())
{
#Html.DropDownListFor(m => m.SelectedId, new SelectList(Model.List, "ID", "Name"), new { autopostback = "true" })
}
The form that your dropdownlist is in will get submitted when you change selection of your dropdownlist. If the result of the action of that form is the same page, it will be reloaded with whatever stuff being updated
$(document).ready(function() {
$("#ddl").change(function() {
var strSelected = "";
$("#ddl option:selected").each(function() {
strSelected += $(this)[0].value;
});
var url = "/Home/MyAction/" + strSelected;
$.post(url, function(data) {
// do something if necessary
});
});
});
or
<%=Html.DropDownListFor(m => m.SelectedId, new SelectList(Model.List, "ID", "Name"), new { onchange="this.form.submit();" })%>
It's simple. In your javascript you have:
$(document).ready(function () {
$('#SelectedId').change(function () {
var id = $(this).val();
$.getJSON("/YourController/YourAction", { id: id},
function (data) {
$("#SomeDivSelector").html(data);
});
});
});
Your controller should look like:
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult YourAction(int id)
{
//do something
return Json(ControlToString("~/Views/YourController/YourView.cshtml", yourModelWithData), JsonRequestBehavior.AllowGet);
}
And ControlToString is defined:
private string ControlToString(string controlPath, object model)
{
//CshtmlView control = new CshtmlView(controlPath);
RazorView control = new RazorView(this.ControllerContext, controlPath, null, false, null);
this.ViewData.Model = model;
using (System.Web.UI.HtmlTextWriter writer = new System.Web.UI.HtmlTextWriter(new System.IO.StringWriter()))
{
control.Render(new ViewContext(this.ControllerContext, control, this.ViewData, this.TempData, writer), writer);
string value = ((System.IO.StringWriter)writer.InnerWriter).ToString();
return value;
}
}
Regards.
What you want to apply, against the concept of the technology you're using.
MVC based on ASP.NET technology, but another way executing. MVC not use better of life cycle of ASP.NET, so, does not "Postback". MVC - in the root based on architectural pattern, that allows to separate the different layers of any system, therefore approach to the development on current technology is completely different. learn more about MVC: http://www.asp.net/mvc
if you want still implement your problem you can use ASP.NET concept and use AutoPostback property of DropDownList control.

Categories