I dont know whats wrong.
I follow this link http://www.dotnetcodesg.com/Article/UploadFile/2/286/CRUD%20operation%20using%20Modal%20Popup%20in%20ASP.NET%20MVC%204.aspx because need pretty same thing: CRUD grid with popup for edit.
I do everything inside HomeController and Index.cshtml which generated by VS2013.
I cut from the code the things involved:
Index.cshtml
grid.Column("", header: "Actions",
format: #<text>
#Html.ActionLink("Edit", "EditConstruct", new { id = item.Id, #class = "editDialog" })
<div id="dialog-edit" style="display: none">
Controller
public ActionResult EditConstruct(int id)
{
var data = advConstructRepository.Get(id);
AdvConstructModel model = new AdvConstructModel
{
Id = data.Id,
Description = data.Description,
MaintenanceTime = data.MaintenanceTime,
Location = data.Location,
Height = data.Height,
Width = data.Width,
MonthlyCost = data.MonthlyCost,
AdvConstructType = advConstructRepository.GetAdvConstructType(data.AdvTypeId)
};
ViewBag.IsUpdate = true;
return View("EditConstruct", model);
}
Edit View
#model AdvApplication.Models.AdvConstructModel
#{
Layout = null;
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
#using (Html.BeginForm("UpdateConstruct", "Home", "POST"))
{
#Html.ValidationSummary(true)
ViewBag.IsUpdate = true;
return View("EditConstruct", model);
}
etc...
But when i clicked on Edit action, i receive fields for edit but not in the popup, but on whole screen as a single page.
EditConstruct view was created as partial view.
Please suggest how to fix
It is probably the whole view being sent back, jquery deals in fragments, not whole pages.
Consider this change:
public ActionResult EditConstruct(int id)
{
var data = advConstructRepository.Get(id);
AdvConstructModel model = new AdvConstructModel
{
Id = data.Id,
Description = data.Description,
MaintenanceTime = data.MaintenanceTime,
Location = data.Location,
Height = data.Height,
Width = data.Width,
MonthlyCost = data.MonthlyCost,
AdvConstructType = advConstructRepository.GetAdvConstructType(data.AdvTypeId)
};
ViewBag.IsUpdate = true;
if(Request.IsAjaxRequest())
return PartialView("EditConstruct", model);
return View("EditConstruct", model);
}
Related
I still relatively new to ASP.Net and the concepts of communicating between client and server. I am using DevExpress tools but I believe this issue is more of a misunderstanding of the concept.
I have a GridView within a partial view that is loaded via an Action #Html.Action('MessageGridView'). This works no problem and data is loaded fine with the index and a returned model.
#Html.DevExpress().GridView(settings =>
{
settings.Width = System.Web.UI.WebControls.Unit.Percentage(100);
settings.Name = "preparedMessagesGrid";
settings.CallbackRouteValues = new { Controller = "Messages", Action = "MessagesGridView" };
settings.KeyFieldName = "Id";
settings.SettingsBehavior.AllowSelectByRowClick = true;
settings.SettingsBehavior.AllowSelectSingleRowOnly = true;
settings.ClientSideEvents.Init = "GridViewInit";
settings.ClientSideEvents.SelectionChanged = "OnSelectionChanged";
settings.ClientSideEvents.BeginCallback = "OnBeginCallback";
settings.SettingsBehavior.AllowEllipsisInText = true;
settings.PreRender = settings.Init = (sender, e) =>
{
MVCxGridView gridView = sender as MVCxGridView;
gridView.Selection.SelectAll();
};
settings.Columns.Add("Name");
settings.Columns.Add("Description");
}).Bind(Model.preparedMessages).GetHtml()
What I am trying to achieve is when the user selects the row I wish the data to be loaded into the popup control when clicked. Is there a way I can set the parameters dynamically for the popup control callback?
#Html.DevExpress().PopupControl(settings =>
{
settings.Name = "pcModalMode";
settings.Width = 100;
settings.AllowDragging = true;
settings.CloseAction = CloseAction.CloseButton;
settings.CloseOnEscape = true;
settings.PopupAnimationType = AnimationType.None;
settings.HeaderText = "Login";
settings.Modal = true;
settings.PopupHorizontalAlign = PopupHorizontalAlign.WindowCenter;
settings.PopupVerticalAlign = PopupVerticalAlign.WindowCenter;
settings.CallbackRouteValues = new { Controller = "Messages", Action = "Load", new { id = THIS NEEDS TO BE SELECTED ID VALUE} };
settings.LoadContentViaCallback = LoadContentViaCallback.OnFirstShow;
}).GetHtml()
It works if I set the value static so I'm one step away from getting this working. What I have researched is that I can get the values from the GridView in javascript using the selection changed event.
function OnSelectionChanged(s, e) {
s.GetSelectedFieldValues("Id", GetSelectedFieldValueCallback);
}
I can then retrieve this value but can I set this to my popup control or am I misunderstanding being relatively new and possibly I could do this server side for when the ViewGrid callback is performed, then set it server side with a session of some sort?
You're just one step away to get currently selected grid value with this function:
function OnSelectionChanged(s, e) {
s.GetSelectedFieldValues('Id', GetSelectedFieldValueCallback);
}
What you need to do is declaring GetSelectedFieldValueCallback method as this (I got from a test that selectedValue contains array with single value for single grid row selection, use zero index to assign the value):
var id; // a global variable set to hold selected row key value from grid
function GetSelectedFieldValueCallback(selectedValue) {
if (selectedValue.length == 0)
return;
id = parseInt(selectedValue[0]);
pcModalMode.PerformCallback();
}
Then setting BeginCallback on PopupControl helper as given below, note that for DevExpress HTML helpers you can use customArgs in client-side to pass action method parameters instead of using CallbackRouteValues with id parameter:
#Html.DevExpress().PopupControl(settings =>
{
settings.Name = "pcModalMode";
// other stuff
settings.CallbackRouteValues = new { Controller = "Messages", Action = "Load" };
settings.ClientSideEvents.BeginCallback = "OnPopUpBeginCallback";
settings.ClientSideEvents.EndCallback = "OnPopUpEndCallback";
// other stuff
}).GetHtml()
// JS function for popup callback
function OnPopUpBeginCallback(s, e) {
e.customArgs["id"] = id; // this sends 'id' as action method parameter to `Load` action
}
// Optional end callback
function OnPopUpEndCallback(s, e) {
if (!pcModalMode.IsVisible())
pcModalMode.Show();
}
Finally, let's putting them all together in view & controller code:
View
<!-- View page -->
<script type="text/javascript">
var id;
function OnSelectionChanged(s, e) {
s.GetSelectedFieldValues('Id', GetSelectedFieldValueCallback);
}
function GetSelectedFieldValueCallback(selectedValue) {
if (selectedValue.length == 0)
return;
id = parseInt(selectedValue[0]);
pcModalMode.PerformCallback();
}
function OnPopUpBeginCallback(s, e) {
e.customArgs["id"] = id;
}
function OnPopUpEndCallback(s, e) {
if (!pcModalMode.IsVisible())
pcModalMode.Show();
}
</script>
GridView (partial view)
#Html.DevExpress().GridView(settings =>
{
settings.Name = "preparedMessagesGrid";
// other stuff
settings.ClientSideEvents.SelectionChanged = "OnSelectionChanged";
}).Bind(Model.preparedMessages).GetHtml()
Popup (partial view)
#Html.DevExpress().PopupControl(settings =>
{
settings.Name = "pcModalMode";
// other stuff
settings.CallbackRouteValues = new { Controller = "Messages", Action = "Load" };
settings.ClientSideEvents.BeginCallback = "OnPopUpBeginCallback";
settings.ClientSideEvents.EndCallback = "OnPopUpEndCallback";
// other stuff
}).GetHtml()
Controller
public class Messages : Controller
{
public ActionResult MessagesGridView()
{
// grid view populating data code lines here
return PartialView("_GridView", data);
}
public ActionResult Load(int id)
{
// code lines to find ID here
return PartialView("_ModalPopup", model);
}
}
References:
(1) Display GridView Row Details in PopupControl Window
(2) How to display detail data within a popup window (MVC)
(3) ASPxClientGridView.GetSelectedFieldValues (DevExpress Documentation)
(4) MVCxClientBeginCallbackEventArgs.customArgs (DevExpress Documentation)
I apologize I am still fairly new to MVC. I currently have a dropdownlist with some options. What I would like to do is depending on the dropdownlist value that I select then I should be able to render a partial view. I want the partial view to load as soon as the user selects from the dropdownlist.
Also, I am able to render my partial view but it's not returning what I need. When I select from the dropdownlist it does not take the functionID..it just returns all of the items regardless of the functionID.
I want the partial view to render based off the functionID.
Thank you very much. Any help is very much appreciated it.
Main View
#Html.DropDownListFor(m => m.FunctionID, new
SelectList(Model.functionList, "FunctionID", "Name"), "Select
Function", new {#id="id"})
<div id="partialPlaceHolder">
</div>
Partial View
#foreach (var items in Model.itemTypeList)
{
<pre> #items.Definitions</pre>
}
Controller
[HttpGet]
public ActionResult ViewOverview()
{
List<Function> functionList;
List<ItemType> itemTypeList;
using (BusinessLogic BLL = new BusinessLogic())
{
functionList = BLL.GetFunctionList();
itemTypeList = BLL.GetItemTypesList();
}
Words viewModel = new Words();
MetricDefinitions(viewModel);
return View(viewModel);
}
[HttpGet]
public ActionResult GetWords()
{
List<Function> functionList;
List<ItemType> itemTypeList;
using (BusinessLogic BLL = new BusinessLogic())
{
functionList = BLL.GetFunctionList();
itemTypeList = BLL.GetItemTypesList();
}
Words viewModel = new Words()
{
itemTypeList = itemTypeList,
functionList = functionList
};
return PartialView("_ViewWords", viewModel);
}
private void MetricDefinitions(Words model)
{
List<Function> functionList;
List<ItemType> itemTypeList;
using (BusinessLogic BLL = new BusinessLogic())
{
functionList = BLL.GetFunctionList();
itemTypeList = BLL.GetItemTypesList();
}
model.functionList = functionList;
model.itemTypeList = itemTypeList;
}
javascript
$(document).ready(function () {
$('#id').change(function () {
var selectedID = $(this).val();
$.get('/Home/GetWords/' + selectedID, function (data) {
$('#partialPlaceHolder').html(data);
/* little fade in effect */
$('#partialPlaceHolder').fadeIn('fast');
});
});
});
I have added NetFiddle. It works here
Can you try to add selectedItem param into action and use jquery .load() function to get partial result into your target element.
[HttpGet]
public ActionResult GetWords(int selectedItem) // add your selectedVal value in controller
{
.....
}
jquery
// it is going to parse partial view into target div
$("#id").on("change", function(){
var url = '#Url.Action("GetWords", "Home")' + "?selectedItem=" + $(this).val();
$("#partialPlaceHolder").load(url, function(){
console.log("It worked");
$('#partialPlaceHolder').fadeIn('fast');
})
})
I have a codemirror editor in a partial view and a list of files in the main view. I want to refresh the editor once a file name is clicked. I tried many solutions provided on StackOverflow and other websites but nothing worked , and This is my first time using Javascript so I can't figure out What am I doing wrong.
This is my code:
Controller:
public ActionResult Index()
{
StudentsCodes model = new StudentsCodes();
model.Student = (Student)CurrentUser;
var user = UserManager.FindById(((Student)CurrentUser).InstructorID);
model.Instructor =(Instructor) user;
return View(model);
}
public PartialViewResult DevelopmentPartial (StudentsCodes path )
{
return PartialView(path);
}
Main view:
<script type="text/javascript" src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
<script type="text/javascript" src="~/Scripts/jquery-3.1.1.js"></script>
<ul id="tree">
#foreach (var file in Directory.GetFiles(Server.MapPath("~/Content/" + Model.Student.UserName + "/CompilerProject/" + name)))
{
var filename = Path.GetFileName(file);
<li id="filelist" onclick="#(Model.path = "~/Content/" + Model.Student.UserName + "/CompilerProject/src/" + #filename)">
<span class="glyphicon glyphicon-file"></span>
#filename
/li>
}
<div id="partial">
#{
Html.RenderPartial("DevelopmentPartial",null);
}
</div>
<script>
$(document).ready(function () {
$("#filelist").click(function (e) {
#{Html.RenderAction("DevelopmentPartial", Model);
}
});
});
</script>
partial view:
#using (Html.BeginForm())
{
var fileContents= "";
if (Model==null)
{
fileContents = "";
}
else
{
fileContents = System.IO.File.ReadAllText(Server.MapPath(Model.path));
}
#Html.TextArea("code", fileContents, new { id = "code" })
}
I can't assign ids for list elements since their number is unknown at compile time and it changes when the user adds or deletes a file, that's why most of the solutions provided didn't work . The result here was 3 editors overlapping and display the contents of the last file. And <li> items are non-clickable. What am I doing wrong in my code ?
Edit:
After updating the script as the following:
<script>
$(document).ready(function() {
$(".filelist").on("click",function (e) {
$("#partial").load('DevelopmentPartial');
});
});
</script>
It refreshes the partial view but the editor is always empty, and the Model is always null. Is it wrong to update the Model using "onclick"?
In case someone faced the same problem, I solved it by changing id to class at the list, then by using this script:
<div id="partial">
#{
Html.RenderAction("DevelopmentPartial", new { path1 = Model.path});
}
</div>
<script>
$(document).ready(function () {
$('.filelist').on('click', function (e) {
alert('Im clicked on filePath = ' + $(this).attr('value'));
var filePath = $(this).attr('value'); //value is attribute set in Html
$('#partial').load('DevelopmentPartial', { path1: filePath });
});
});
</script>
And the controller:
public PartialViewResult DevelopmentPartial(string path1)
{
modelSC.path = path1;
return PartialView(modelSC);
}
where modelSC is a global variable in the controller.
Controller:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class ExperimentalController : Controller
{
public ActionResult ReloadTest1()
{
string temp = DateTime.Now.ToString();
ViewBag.Time = temp;
return View();
}
public PartialViewResult ReloadTest1Partial()
{
string temp = DateTime.Now.ToString();
ViewBag.Time = temp;
return PartialView();
}
}
View:
#{
ViewBag.Title = "ReloadTest1";
string time = this.ViewBag.Time;
ViewData["date"] = time;
ViewBag.TheTitle = "test";
}
<h2>ReloadTest1</h2>
<select id="iSelect" name="iSelect" >
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
<div id="myPartialViewContainer">
#{Html.RenderPartial("_ReloadTest1Partial", null, new ViewDataDictionary { {"vb", ViewBag}});}
</div>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script>
$('#iSelect').on('change', function () {
$("#myPartialViewContainer").load('#(Url.Action("ReloadTest1Partial", "Experimental", null, Request.Url.Scheme))')
})
</script>
Partial View:
#{
var vb = ((dynamic)ViewData["vb"]);
}
<div>
<span>#vb.Time</span>
</div>
What is not working:
Passing the viewbag/viewdata directly from controller to partial view because mvc does not accept that to happen.
What is working:
from the above code you can see that the partial view gets the data ONCE with the Html.RenderPartial method and the viewbag passing down.
the reload does work on change of the selected object in the dropdown
What is needed:
I need to pass data to the partial view when it is reloaded or afterwards, this is mainly a test setup but i finally want to be able to update tables dependant on the select value.
If somone is able to give me a working example please do so.
In your controller you;re using ViewBag to set custom value, but in your view you are working with ViewData as well as referring to a different name (you're setting ViewBag's Time property in controller, but you expect ViewData's vb property in the view).
Change your view to expect model`:
#model MyModel
#{
string time = "";
if (ViewData["Time"] != null)
{
time = ViewData["Time"];
}
}
<div>
<span>#Model.Time</span>
</div>
And change you controller to pass it:
public ActionResult ReloadTest1()
{
var model = new MyModel {Time = DateTime.Now.ToString()};
return View(model);
}
public PartialViewResult ReloadTest1Partial()
{
var model = new MyModel {Time = DateTime.Now.ToString()};
return PartialView(model);
}
And you master view file will look like this:
#model MyModel
<div id="myPartialViewContainer">
#{Html.RenderPartial("_ReloadTest1Partial", model);}
</div>
And create your model:
public class MyModel
{
public string Time {get;set;}
}
As a side not, it's always preferable to use a strongly-typed model instead of ViewBag or ViewData as you can get compilation errors and IntelliSense
Final solution:
Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
namespace RolloutTool.Controllers
{
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class ExperimentalController : Controller
{
public ActionResult ReloadTest1()
{
var model = new RolloutTool.Models.ExperimentalViewModels.MyModel { Time = DateTime.Now.ToString() };
string temp = DateTime.Now.ToString();
ViewBag.Time = temp;
ViewData["Time"] = temp;
return View(model);
}
[HttpPost]
public PartialViewResult ReloadTest1Partial(string test)
{
var model = new RolloutTool.Models.ExperimentalViewModels.MyModel { Time = DateTime.Now.ToString() };
string temp = DateTime.Now.ToString();
ViewBag.Time = temp;
ViewData["Time"] = temp;
return PartialView("_ReloadTest1Partial", model);
}
// GET: Experimental
public ActionResult Experimental()
{
ViewBag.Message = "Your contact page.";
ViewBag.TestValue = 10;
string[] temp = { "alpha", "beta", "gamma", "delta" };
ViewBag.names = temp;
int temp2 = temp.Length;
ViewBag.nameslength = temp2;
return View();
}
}
}
View:
#{
ViewBag.Title = "ReloadTest1";
string time = this.ViewBag.Time;
ViewData["date"] = time;
ViewBag.TheTitle = "test";
}
#model RolloutTool.Models.ExperimentalViewModels.MyModel
<h2>ReloadTest1</h2>
<select class="chosen-select" id="iSelect" name="iSelect">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
<div id="myPartialViewContainer">
#{Html.RenderPartial("_ReloadTest1Partial", Model);}
</div>
#Styles.Render(
"~/content/chosen/chosen.css",
"~/content/chosen/prism.css",
"~/content/chosen/style.css",
"~/content/bootstrap.css",
"~/content/Site.css")
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/chosen/chosen.jquery.js"></script>
<script src="~/Scripts/chosen/prism.js"></script>
<script>
var config = {
'.chosen-select': {},
'.chosen-select-deselect': { allow_single_deselect: true },
'.chosen-select-no-single': { disable_search_threshold: 10 },
'.chosen-select-no-results': { no_results_text: 'Oops, nothing found!' },
'.chosen-select-width': { width: "95%" }
}
for (var selector in config) {
$(selector).chosen(config[selector]);
}
</script>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script>
$('#iSelect').on('change', function () {
getPartial();
})
</script>
<script>
function getPartial() {
var tempSelect = document.getElementById("iSelect");
var tempResult = tempSelect.options[tempSelect.selectedIndex].text;
$.ajax({
url: "ReloadTest1Partial",
type: "POST",
data: {'test' = tempResult}, //if you need to post Model data, use this
success: function (result) {
$("#myPartialViewContainer").html(result).find("select").each(function () {
$(this).chosen({});
}
});
}
</script>
#{
string time = "";
string temp = "";
if (ViewData["vb"] != null)
{
temp = "1";
time = ((dynamic)ViewData["vb"]).Time;
}
else if (ViewContext.Controller.ViewBag.Time != null)
{
temp = "2";
time = ViewBag.Time;
}
else if (ViewData["Time"] != null)
{
temp = "3";
time = (string) ViewData["Time"];
}
}
#model RolloutTool.Models.ExperimentalViewModels.MyModel
<div>
<span>#time</span>
<span>#Model.Time</span>
<span>#temp</span>
</div>
<select class="chosen-select"></select>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/chosen/chosen.jquery.js"></script>
<script src="~/Scripts/chosen/prism.js"></script>
This updates the partial view correctly AND reloads the chosen-select dropdowns. (see styles and scripts not working in partial view)
I'm having two dropdown lists in my MVC(Razor) view: Country and State.
I'm able to fill both the dropdown's independent of each other.Now i want to fill second dropdown(State) based on the change event of Country's dropdown.
For this I have used JsonResult method in Controller and for this method i'm passing countryID on the Change event of Country from my view inorder to fill my second dropdown state.
Problem Statement: The JsonResult method is getting triggered from my view but the CountryId value is not getting passed from view to controller in-order to fill state.
What i'm doing wrong here?
View:
Javascript:
<script type="text/JavaScript">
function CountryChange() {
var url = '#Url.Content("~/MasterConfigGeneral/GetState")';
var ddlsource = "#CountryID";
var ddltarget = "#StateID";
if ($(ddlsource).val() != "") {
$.ajaxSetup({ cache: false });
$.getJSON(url, { countryID: $(ddlsource).val() }, function (data) {
$(ddltarget).empty();
$("#StateID").append("<option value=''>Select State</option>");
$.each(data, function (index, optionData) {
$("#StateID").append("<option value='" + optionData.Value + "'>" + optionData.Text + "</option>");
});
});
}
else {
$("#StateID").empty();
$("#StateID").append("<option value=''>Select State</option>");
}
}
</script>
Dropdown's in my View:
<div class="cssclass">
#Html.DropDownListFor(model => model.companyModel.CountryID, new SelectList(Model.ddlCountryStateCity.ddlCountry, "Value", "Text"), "Select Country", new { onchange="CountryChange()" })
#Html.ValidationMessageFor(model => model.companyModel.CountryID)
</div>
<div class="cssclass">
#Html.LabelFor(model => model.companyModel.StateID)
</div>
<div class="editor-field">
#Html.DropDownList("stateid",Model.ddlCountryStateCity.ddlState,"Select State")
#Html.ValidationMessageFor(model => model.companyModel.StateID)
</div>
Controller:
Country Dropdown:
#region Country
public DropdownListCountryStateCity FillDropDownListCountry()
{
objDropDownCountryStateCity.ddlCountry = (from s in dbEntity.Countries
select new SelectListItem()
{
Text = s.Name,
Value = s.CountryID
}).ToList<SelectListItem>();
return objDropDownCountryStateCity;
}
#endregion
State Dropdown:
#region State
public JsonResult GetState(string countryID)
{
JsonResult jsResult = new JsonResult();
objDropDownCountryStateCity.ddlState = (from csc in dbEntity.CountryStateCities
join c in dbEntity.Countries on csc.CountryID equals c.CountryID
join s in dbEntity.States on csc.StateID equals s.StateID
where csc.CountryID == countryID
select new SelectListItem()
{
Text = s.Name,
Value = s.StateID
}).ToList<SelectListItem>();
jsResult.Data = objDropDownCountryStateCity.ddlState;
jsResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return jsResult;
}
#endregion
Your problem lies on how the DropDownListFor helper generates the element.
In your code, it's generating names and ids something like this:
<select id="companyModel_CountryID" name="companyModel.CountryID">
...
</select>
In your javascript the ddlSouce is "#CountryID". Since there's no element with that id, jQuery pass null as data to $.getJSON. That's why the controller method receives nothing.
You have two options:
Change ddlSource javascript to the proper id (you'll have to see on the source code) OR
Change the last DropDownListFor helper from
new { onchange="CountryChange()" }
to
new { id = "CountryID", onchange="CountryChange()" }
IMHO, the last option is the best choice.