Update kendo grid columns without page reload in ASP MVC - asp.net-mvc-4

I have a kendo grid where user can select list of columns from grid and save the selection by giving name (i.e view name). Each saved selection (view name) will show up as drop-down above grid so that user can change grid columns whenever they want. In current implementation, whenever user selects view name from one drop-down value to other, i call action method to select that view name as current view name. Then page reloads to invoke Index' action method to retrieve current view names columns values. I am using visible attribute in grid to show and hide columns in grid.
Now i was wondering if i can update the grid columns without reloading the page when user change the view name from the dropdown.
Thanks
Sanjeev
Screenshot:
Here is my setup:
ViewModel:
namespace MvcApplicatioin.Models
{
public class EmployeeViewModel
{
public EmployeeColumns EmployeeColumns { get; set; }
public IEnumerable<SelectListItem> EmployeeViewNames { get; set; }
public long EmployeeSelectedViewId { get; set; }
}
public class EmployeeResponse
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class EmployeeColumns
{
public bool Id { get; set; }
public bool FirstName { get; set; }
public bool LastName { get; set; }
}
}
Controller:
public class EmployeeController : Controller
{
// GET: Employee
public ActionResult Index()
{
var service = new EmployeeService();
EmployeeViewModel model = new EmployeeViewModel();
long currentViewId;
//setup views and column preferences
EmployeeColumns employeeColumns = service.GetCurrentEmployeeColumnsPreferences();
model.EmployeeColumns = employeeColumns;
model.EmployeeViewNames = service.GetAllEmployeeViewNames(out currentViewId);
model.EmployeeSelectedViewId = currentViewId;
return View(model);
}
}
Razor:
#using Kendo.Mvc.UI
#{
ViewBag.Title = "Employee Info:";
}
<h3 style="margin-bottom: 10px;">Employee Info</h3>
<input id="btnSearch" type="button" value="Search" class="btn_Search" />
<div class="row">
<div class="col-sm-12">
#(Html.Kendo().Grid<MvcApplicatioin.Models.EmployeeResponse>()
.Name("GridEmployee")
.Columns(columns =>
{
columns.Bound(e => e.Id).Width("170px").Visible(Model.EmployeeColumns.Id);
columns.Bound(e => e.FirstName).Width("190px").Visible(Model.EmployeeColumns.FirstName);
columns.Bound(e => e.LastName).Width("170px").Visible(Model.EmployeeColumns.LastName);
})
.ToolBar(tools =>
{
tools.Template(#<text>
<div class="col-lg-4 col-md-5 col-sm-5 col-xs-7 pull-right" style="padding-right: 0;">
<div class="form-group" style="margin-bottom: 0;">
#Html.Label("Grid View:", new { #class = "col-sm-3 col-xs-4 control-label view" })
<div class="col-sm-7 col-xs-6" style="padding-left: 0;">
#Html.DropDownList("lstEmployeeViewNames", new SelectList(Model.EmployeeViewNames, "Value", "Text", Model.EmployeeSelectedViewId), "- Select View Name -", new { #class = "form-control", #style = "height: auto;" })
</div>
</div>
</div>
</text>);
})
.Pageable(x => x.PageSizes(new int[] { 10, 20, 50, 100 }).ButtonCount(4))
.AutoBind(false)
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(10)
.ServerOperation(false)
.Read(read => read.Action("SearchEmployee", "Employee")))
)
</div>
</div><!--//row-->
<script type="text/javascript">
$('#btnSearch').click(function (e) {
e.preventDefault(); //This prevent the submit button onclick from submitting by itself
$('#GridEmployee').data('kendoGrid').dataSource.read();
});
//Change event for Dropdown placed inside the Grid's Toolbar - To Change the view
$("#lstEmployeeViewNames").change(function (e) {
var selectedViewId = $('select#lstEmployeeViewNames option:selected').val();
if (selectedViewId == null || selectedViewId == '') {
alert("Please select the view name from the dropdown first !!");
return;
}
$.post("/Employee/SetEmployeeColumnsCurrentPreferences", { viewId: selectedViewId }, function (data) {
window.top.location.reload();
});
});
</script>

This is how I would do a search in client. I know it doesn't tell how to show and hide columns, but at least it could put you on the right track.
The trick is to manipulate $("#GridEmployee") instead of posting.
function search() {
var searchCriteria = $("#searchField").val();
var gridData = $("#GridEmployee").data("kendoGrid");
if searchCriteria != "") {
gridData.dataSource.filter({ field: "FirstName", operator: "contains", value: searchCriteria });
} else {
gridData.dataSource.filter({});
}
}

Related

My Bootstap modal form is covering the entire screen

I have a modal form in my ASP.NET Core 3.1 project. The problem is my modal form unexpectedly is covering entire of screen and I don't know why.
My _Modal.cshtml:
#model MyProject.CommonLayer.PublicClass.BootstrapModel
<div aria-hidden="true" aria-labelledby="#Model.AreaLabeledId" role="dialog" tabindex="-1" id="#Model.ID" class="modal fade">
<div class="modal-dialog #Model.ModalSizeClass">
<div class="modal-content" style="border-radius:6px;">
</div>
</div>
</div>
My modal.js file:
(function ($) {
function Modal() {
var $this = this;
function initilizeModel() {
$("#modal-action").on('loaded.bs.modal', function (e) {
}).on('hidden.bs.modal', function (e) {
$(this).removeData('bs.modal');
});
}
$this.init = function () {
initilizeModel();
}
}
$(function () {
var self = new Modal();
self.init();
})
}(jQuery))
and my BooststrapModal.cs file:
public class BootstrapModel
{
public string ID { get; set; }
public string AreaLabeledId { get; set; }
public ModalSize Size { get; set; }
public string Message { get; set; }
public string ModalSizeClass
{
get
{
switch (this.Size)
{
case ModalSize.Small:
return "modal-sm";
case ModalSize.Large:
return "modal-lg";
case ModalSize.Medium:
default:
return "";
}
}
}
public enum ModalSize
{
Small,
Large,
Medium
}
}
In the end of my index.cs file, for modal I put:
#Html.Partial("_Modal", new BootstrapModel { ID = "modal-action", Size = BootstrapModel.ModalSize.Medium })
#section AdminScripts {
<script src="~/js/modal/modal.js"></script>
}
Finally when button is clicked, the modal form covers my entire screen.
Please help. Thanks in advance.

MVC checkbox list bounding to model

I am trying to collect all the options that the user have selected for a checkbox list. The checkbox list is built using a foreach loop and I have a int[] that I am trying to put the id into. Any help would be great.
View
#{
int idxFormats = 0;
foreach (var item in Model.ListOfFormats)
{
<div class='col-md-6'>
<input type="checkbox" value=#item.Value name="chkFormat" />
<label asp-for=#item.Selected>#Html.Raw(#item.Name)</label>
#Html.HiddenFor(m => Model.selectedFormats[idxFormats]);
</div>
idxFormats++;
}
#Html.ValidationMessageFor(model => model.selectedFormats[idxFormats])
}
Model
public List<GenericValues> ListOfFormats { get; set; }
[Display(Name = "At least one 'Format' must be selected")]
public int[] selectedFormats { get; set; }
Change the Checkbox name to selectedFormats
<input type="checkbox" value=#item.Value name="selectedFormats" />
Test example:
Model:
public class Test
{
public List<GenericValues> ListOfFormats { get; set; }
public int[] selectedFormats { get; set; }
}
public class GenericValues
{
public int Value { get; set; }
public string Name { get; set; }
public bool Selected { get; set; }
}
View:
#model Test
#{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Index</h1>
<form method="post">
#{
foreach (var item in Model.ListOfFormats)
{
<div class='col-md-6'>
<input type="checkbox" value=#item.Value name="selectedFormats" />
<label asp-for=#item.Selected>#Html.Raw(#item.Name)</label>
</div>
}
}
<input type="submit" value="submit" />
</form>
Controller:
public IActionResult Index()
{
Test test = new Test
{
ListOfFormats = new List<GenericValues>
{
new GenericValues
{
Name = "A",
Value = 1,
},
new GenericValues
{
Name = "B",
Value = 2,
},
new GenericValues
{
Name = "C",
Value = 3,
}
}
};
return View(test);
}
[HttpPost]
public IActionResult Index(Test test)
{
return Ok();
}
Result:
if you are looking to put id as value of your idxFormats then use this code in your checkbox:
<input type="checkbox" value=#item.Value name="chkFormat" id="#idxFormats" />
Edit:
I am not so familiar with c#, I tested with minimum code :
// Replace the model correct path by yours
#model IEnumerable<WebApplication1.Models.MyModels.ListOfFormats>
#{
int idxFormats = 0;
foreach (var item in Model)
{
<div class='col-md-6'>
<input type="checkbox" value=#item.Value name="chkFormat" id="#idxFormats"/>
<label>#Html.Raw(#item.Name)</label>
</div>
idxFormats++;
}
}

How to dynamically add an item to a list within a list in a ViewModel using Razor and .NET Core 2.2?

I've been following this tutorial (i did it in asp.net core 2.2):
http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/ on how to edit a variable lenght list in asp.net. In this tutorial, we're just handling a list of gifts. I'm trying to apply this method to a more complex model.
I have an object called Workout.cs who contains a List of Section.cs. The Section.cs object contains a List of Movement.cs
public class Workout
{
public string Name { get; set; }
public IEnumerable<Section> Sections { get; set; } = new List<Section>();
}
public class Section
{
public int NbRounds { get; set; }
public string Name { get; set; }
public IEnumerable<Movement> Movements { get; set; } = new List<Movement>();
}
public class Movement
{
public string Name { get; set; }
}
WorkoutController
public IActionResult BlankSection()
{
return PartialView("_SectionEditor", new Section());
}
public IActionResult BlankMovement()
{
return PartialView("_MovementEditor", new Movement());
}
Index.cshtml
#model Workout
<h2>Workout</h2>
<form asp-action="Index" method="post" asp-controller="Workout">
<div id="editorRows">
#foreach (var item in Model.Sections)
{
<partial name="_SectionEditor" model="item" />
}
</div>
<a id="addItem" asp-action="BlankSection" asp-controller="Workout">Add Section...</a> <br />
<input type="submit" value="Finished" />
</form>
#section scripts {
<script>
$("#addItem").click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (html) { $("#editorRows").append(html); }
});
return false;
});
</script>
}
_SectionEditor.cshtml
#model Section
#{
Layout = "~/Views/Shared/_LayoutEditor.cshtml";
}
<div class="editorRow">
#using (Html.BeginCollectionItem("sections"))
{
<span>Name: </span> #Html.EditorFor(m => m.Name);
<span>Rounds: </span>#Html.EditorFor(m => m.NbRounds, new { size = 4 });
}
delete
<div id="editorMovement">
#foreach (var item in Model.Movements)
{
<partial name="_MovementEditor" model="item" />
}
</div>
<a id="addMovement" asp-action="BlankMovement" asp-controller="Workout">Add Movement...</a> <br />
</div>
#section Scripts {
<script>
$(document).ready(function () {
$("a.deleteRow").on("click", function () {
$(this).parents("div.editorRow:first").remove();
return false;
});
});
$("#addMovement").click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (html) { $("#editorMovement").append(html); }
});
return false;
});
</script>
}
MovementEditor.cshtml
#model Movement
#{
Layout = "~/Views/Shared/_LayoutEditor.cshtml";
}
<div class="editorMovement">
#using (Html.BeginCollectionItem("movements"))
{
<span>Name: </span> #Html.TextBoxFor(m => m.Name);
}
delete
</div>
#section Scripts {
<script>
$(document).ready(function () {
$("a.deleteMovement").on("click", function () {
$(this).parents("div.editorMovement:first").remove();
return false;
});
});
</script>
}
With the tutorial, it's working fine when I'm adding sections to my workout, but when I'm trying the same to add movements to my sections, it's not working anymore. I would like to be able to add as many sections as I want to my workout, and for each section, as many movements as I want, and send it to the controller. How could I do that ?
thanks a lot
First: MovementEditor appears to be a partial in the controller, but not in the view file (despite the '_').
Second: since _SectionEditor is a partial view, you can't define #section scripts in it, because it's already defined in the main view Index. To solve this issue, you need to put all the scripts in the main view Index.
P.S: don't forget to change jquery selectors for items in the partial views, i.e: $("#addMovement") will not point to the anchor tag because it was not there when the DOM tree was created. Instead write $("body #addMovement") and it will get the anchor tag.

Hot Towel SPA Modal Dialog knockout bindings and validation

I'm building a SPA using the Hot Towel SPA template.
Here's my problem:
I have a view where I put the information related to a Venue (Name, Description, Address, etc.)
Associated with the Venue there are different Rooms with their own fields (Name, Description, Type, etc.)
I have a list of Rooms and a button "Add New Room".When I hit the button, a modal dialog pops up, I fill the form with the requested information then I save. After the dialog is closed the list gets updated.
I am able to retrieve the information from the dialog, but I'm not able to trigger the validation rules if the fields are left blank. Also the datacontext.HasChanges() returns always true.
Is it possible to use the modal dialog like any other view?
Here's part of the code I am using:
From Model.cs:
public class Venue
{
[Key]
public int VenueId { get; set; }
[Required(ErrorMessage = "Venue Name is required.")]
[Display(Name = "Venue Name")]
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Room> Fields { get; set; }
...
}
public class Room
{
[Key]
public int RoomId { get; set; }
[Required(ErrorMessage = "Name is required.")]
[Display(Name = "Name")]
public string Name { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
public int VenueId { get; set; }
public virtual Venue Venue { get; set; }
...
}
From venuedetail.js:
define(['services/datacontext',
'services/model',
'durandal/plugins/router',
'durandal/system',
'durandal/app',
'services/logger',
'viewmodels/roommodal'],
function (datacontext, model, router, system, app, logger, roommodal) {
...
var addRoom = function () {
var newRoom= datacontext.manager.createEntity("Room");
roommodal.room = newRoom;
app.showModal(roommodal).then(function (response) {
if (response) {
}
return true;
});
};
...
From roommodal.js:
define(['durandal/app', 'services/datacontext', 'durandal/system', 'durandal/plugins/router', 'services/logger'],
function (app, datacontext, system, router, logger) {
var isSaving = ko.observable(false);
var room= ko.observable();
activate = function(routeData) {
return true;
};
hasChanges = ko.computed(function() {
return datacontext.hasChanges(); // Always true ?
});
canSave = ko.computed(function() {
return hasChanges() && !isSaving();
});
canDeactivate = function () {
return true;
};
var save = function(dialogResult) {
this.modal.close(dialogResult);
};
var cancel = function() {
this.modal.close(false);
};
var vm = {
activate: activate,
save: save,
canSave: canSave,
cancel: cancel,
canDeactivate: canDeactivate,
room: room,
hasChanges: hasChanges,
title: 'Add room'
};
return vm;
From roommodal.html:
<div class="messageBox">
<div class="modal-header">
<h3 data-bind="text: title"></h3>
<i class="icon-asterisk" data-bind="visible: hasChanges"></i>
</div>
<div class="modal-body">
<div data-bind="with: room">
<label for="name">Name</label>
<input id="name" data-bind="value: name, valueUpdate: 'afterkeydown'"
placeholder="Enter name" />
<div>
<label>Description</label>
<textarea data-bind="value: description"
placeholder="Enter description"></textarea>
</div>
<div>
<label>Notes</label>
<textarea data-bind="value: notes"
placeholder="Enter notes"></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-info"
data-bind="click: cancel, enable: canSave">
<i class="icon-undo"></i>Cancel</button>
<button class="btn btn-info"
data-bind="click: save, enable: canSave">
<i class="icon-save"></i>Save</button>
</div>
Any help will be greatly appreciated.
Thanks in advance.
Validation is triggered when you try to save using datacontext.saveChanges() which you don't do in this piece of code, instead, you are just closing the modal window.
Easiest way to see if saving was successful is to check HasChanges afterwards - it should be false if everything went well, otherwise it will be true.
datacontext.HasChanges() returns true when you enter modal window because you create an entity and place it in your context before opening the modal window. You can only ignore HasChanges and silently CancelChanges before closing the modal window.

MVC4 sending model propert id to controller class

How to send id of a model property Name to Controller class in an MVC4 application
public class{
public Name{get;set;}
}
For Accesing name using id of that property
Update:
Here if change Name using jquery at runtime i want to send the changed name id to the controller class
UPDate:
This is my VIew
<script type="text/javascript">
$(function () {
$('.editor input').blur(function () {
$(this).hide();
$(this).closest('p').find('label').html($(this).val()).show();
});
$('.editor label').click(function () {
$(this).hide();
$(this).closest('p').find('input').show();
});
});
#using (Html.BeginForm("Homepage", "Home", FormMethod.Post))
{
<div class="editor">
<p>
#Html.LabelFor(x => x.Name, Model.Name)
#Html.EditorFor(x => x.Name)
<input type="submit" value="OK" />
</p>
<p>
#Html.LabelFor(x => x.Company, Model.Company)
#Html.EditorFor(x => x.Company)
<input type="submit" value="OK" />
</p>
<p>
#Html.LabelFor(x => x.City, Model.City)
#Html.EditorFor(x => x.City)
<input type="submit" value="OK" />
</p>
</div>
<input type="submit" value="OK" />
}
This is my model
public class Details
{
public string Name
{ get; set; }
public string Company
{ get; set; }
public string City
{ get; set; }
}
This is my COntroller methods
public ActionResult Homepage(Details d)
{
d.Name = "Rakesh";
d.Company = "TCS";
d.City = "DElhi";
return View(d);
}
[HttpPost, ActionName("Homepage")]
public ActionResult Indexof(Details d)
{
return View(d);
}
Here i am editing and sending data to the controller but my problem is when i click on Rakesh for example and change the name then i need to click button twice then only the changed data is sent to the controller class
Model:
public class SomeModel {
public string Name { get; set; }
}
Controller:
[HttpPost]
public ActionResult YourAction( SomeModel m )
{
if( ModelState.IsValid )
{
// use model
var name = m.Name;
return RedirectToAction( "Index", "Home" );
}
return View( m );
}
If this isn't what you need, please clarify what's this "id" you're talking about.