Grid.Mvc.Ajax extension grid initialization - javascript

Hi I'm very new to Web GUI dev using JQuery & Ajax and I'm trying to get the nuget package Grid.MVC.Ajax working. The readme states the following:
Follow thse steps to use Grid.Mvc.Ajax
1. Include ~/Scripts/gridmvc-ext.js after your ~/Scripts/grimvc.js include.
2. Include ~/Content/ladda-bootstrap/ladda-themeless.min.css CSS after your Bootstrap CSS/LESS include.
3. Include Ladda-bootstrap Javascript via the ~/Scripts/ladda-bootstrap/ladda.min.js
and ~/Scripts/ladda-bootstrap/spin.min.js.
4. Create a view model for you grid data, for example:
public Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
5. Add a Razor partial view for your grid data that uses an AjaxGrid<T> as the model type,
Where T is your view model type:
#using GridMvc.Html
#using GridMvc.Sorting
#model Grid.Mvc.Ajax.GridExtensions.AjaxGrid<Models.Person>
#Html.Grid(Model).Columns(columns =>
{
columns.Add(c => c.FirstName);
columns.Add(c => c.LastName);
}).Sortable(true).WithPaging(10)
6. Add a controller action to retrieve the data for the first page of data that includes the Ajax pager HTML:
public JsonResult Persons()
{
var vm = new List<Person>()
{
new Person() { FirstName = "John", LastName = "Doe" }
}
.AsQueryable();
var ajaxGridFactory = new Grid.Mvc.Ajax.GridExtensions.AjaxGridFactory();
var grid = ajaxGridFactory.CreateAjaxGrid(vm, 1, false);
}
7. Add a controller action to retrieve data for paged items that returns a JsonResult without the Ajax page HTML:
public JsonResult PersonsPaged(int page)
{
var vm = new List<Person>()
{
new Person() { FirstName = "John", LastName = "Doe" }
}
.AsQueryable();
var ajaxGridFactory = new Grid.Mvc.Ajax.GridExtensions.AjaxGridFactory();
var grid = ajaxGridFactory.CreateAjaxGrid(vm, page, true);
}
8. Call the ajaxify Grid.Mvc.Ajax JavaScript plug-in method setting the non-paged and paged controller actions and optionally a form
to apply additional filtering to the grid. All input and select elements in the given form will be passed into your paged and non-paged controller actions:
$(".grid-mvc").gridmvc().ajaxify({
getPagedData: '/Home/Persons',
getData : '/Home/PersonsPaged',
gridFilterForm: $("#gridFilters")
});
I have set things up as stated but I'm having problems in step 8. as I'm not sure how to call the JavaScript code in order to populate the grid. I have enclosed the above in a $(document).ready call but that doesn't seem to work :-( Any help would be much appreciated. Thanks

You have two options: loadPage and refreshFullPage
this will call your PersonsPaged method:
$(".grid-mvc")
.gridmvc()
.loadPage()
and this will call your Persons method.
$(".grid-mvc")
.gridmvc()
.refreshFullGrid()
also, in your Persons and PersonsPaged you can return a JSON like this:
public ActionResult Persons()
{
var vm = new List<Person>()
{
new Person() { FirstName = "John", LastName = "Doe" }
}.AsQueryable();
var ajaxGridFactory = new AjaxGridFactory();
var grid = ajaxGridFactory.CreateAjaxGrid(vm, 1, false);
return Json(new { Html = grid.ToJson("_YourPartialWithGridCode", this), grid.HasItems },JsonRequestBehavior.AllowGet);
}

I resolved the problem adding the URI.js file on the scripts tag before gridmvc.js and gridmvc-ext.js. When I installed Grid.Mvc.Ajax by Nuget, it added this file.
I called the code inside the $(document).ready(function() { ... }) and used twice ways.
1 - The javascript object of the grid using the grid's name.
2 - I did the same way that you did calling ajaxify method after gridmvc method using a jquery selector and it worked to me.
<script>
$(document).ready(function () {
$(".grid-mvc").gridmvc().ajaxify(
{
getPagedData: "/Product/Grid",
getData: "/Product/Index"
});
});
</script>
or
<script>
$(document).ready(function () {
pageGrids.productGrid.ajaxify(
{
getPagedData: "/Product/Grid",
getData: "/Product/Index"
});
});
</script>
"productGrid" is the grid's name. I hope to have helped.

Related

Reload page based on a selection from drop down list MVC

I have a working solution, but I don't know how to reload the page after a certain ID is selected from the drop down list. My list is being populated from the DB. When I select it, I can see the ID and the corresponding data for it. However, there is no change on the screen.
Model class:
public List<Hello> getID()
{
var que = (from rel in db.Table1
select new Hello
{
ID = rel.R_ID
}).ToList();
return que;
}
public List<Hello> getStuff()
{
var que = (from wre in db.View
select new Hello
{
ID = wre.R_ID,
Summary = wre.Summary,
Description = wre.Description
}
}
getHello() is the same exact method as the getStuff(), just accepts a string ID parameter.
Controller class:
public ActionResult Index()
{
var model = test.getStuff();
ViewBag.IDs = new SelectList(test.getID(), "", "ID");
return View(model);
}
[HttpPost]
public JsonResult getDataBySelectedID(string selectedId)
{
var que = test.getHello(selectedId);
return Json(que, JsonRequestBehavior.AllowGet);
}
Partial_View Class:
<div class="container">
<table id="myTable" align="left">
<tr>
<th>#Html.DisplayNameFor(model => model.R_ID)</th>
<th>#Html.DisplayNameFor(model => model.Summary)</th>
<th>#Html.DisplayNameFor(model => model.Description)</th>
</tr>
#foreach (var item in Model)
{
<tr id="Home">
<td>#Html.DisplayFor(x => item.R_ID)</td>
<td>#Html.DisplayFor(x => item.Summary)</td>
<td>#Html.DisplayFor(x => item.Description)</td>
</tr>
}
</table>
</div>
View Class:
#Html.DropDownList("ID", ViewBag.IDs as SelectList)
<script>
$(document).ready(function () {
$("#ID").on("change", function () {
var selectedId = this.value;
var url = "/Sample/getDataBySelectedID";
$.ajax({
method: "POST",
dataType: "json",
url: url,
data: {
selectedId: selectedId
}
});
});
});
</script>
#foreach (var item in Model)
{
<tr>
<td>
#{Html.RenderPartial("Partial_Index", item);}
</td>
</tr>
}
How would I be able to reload the page with the selected value and its corresponding data?
Any help would be appreciated!
Thank you.
As described in the comments, you'll have to load your data into your page somehow. I recommend you do this through partial views.
1) Create a reusable Partial View
First, create a partial view that references your model. To do this, create a view as you normally would for your controller, and tick the "Partial View" option. Make sure to select your model in the model dropdown.
Then, move your .cshtml that references your model from your current view to your partial view. For example, if you have a table that lists out the fields of your model, you would cut the entire table into your partial view. You want to include the minimal amount of code needed in the partial view (aka, don't copy your entire view into it).
2) Reference the Partial View in your Current View
Now that you have your partial view set up, you should use it in your existing view to load the table. You should make sure this works first before continuing. You can use the #Html.RenderPartial(string ViewName, object Model) helper method to render it. Read more. So, you might place this line where your now-cut-code was: #RenderPartial("MyPartialView", model), where "MyPartialView" is the name of your partial view, and model is the model object that you want to pass into the partial view.
3) Add Methods to Render Partial View on Controller
At this point, you just need to be able to update your partial view after using AJAX. First, you need to add the ability to render the Partial View as a string so that you can easily inject it into your view. I recommend you do this by implementing a controller interface and letting your controller inherit the needed methods from that. In my programs, I have the following controller interface that my controllers inherit from:
public class IBaseController : Controller
{
internal string PartialViewToString(string partialViewName, object model = null)
{
ControllerContext controllerContext = new ControllerContext(Request.RequestContext, this);
return ViewToString(
controllerContext,
ViewEngines.Engines.FindPartialView(controllerContext, partialViewName) ?? throw new FileNotFoundException("Partial view cannot be found."),
model
);
}
protected string ViewToString(string viewName, object model = null)
{
ControllerContext controllerContext = new ControllerContext(Request.RequestContext, this);
return ViewToString(
controllerContext,
ViewEngines.Engines.FindView(controllerContext, viewName, null) ?? throw new FileNotFoundException("View cannot be found."),
model
);
}
protected string ViewToString(string viewName, string controllerName, string areaName, object model = null)
{
RouteData routeData = new RouteData();
routeData.Values.Add("controller", controllerName);
if (areaName != null)
{
routeData.Values.Add("Area", areaName);
routeData.DataTokens["area"] = areaName;
}
ControllerContext controllerContext = new ControllerContext(HttpContext, routeData, this);
return ViewToString(
controllerContext,
ViewEngines.Engines.FindView(controllerContext, viewName, null) ?? throw new FileNotFoundException("View cannot be found."),
model
);
}
private string ViewToString(ControllerContext controllerContext, ViewEngineResult viewEngineResult, object model)
{
using (StringWriter writer = new StringWriter())
{
ViewContext viewContext = new ViewContext(
ControllerContext,
viewEngineResult.View,
new ViewDataDictionary(model),
new TempDataDictionary(),
writer
);
viewEngineResult.View.Render(viewContext, writer);
return writer.ToString();
}
}
}
Then, on your controller you can inherit from this interface like so:
public class ExampleController : IBaseController
{
}
Now, you can use the new methods to easily render your partial view to a string.
In your getDataBySelectedID action, this is what you'll want to do.
[HttpPost]
public JsonResult getDataBySelectedID(string selectedId)
{
var que = test.getHello(selectedId);
string partialViewString = PartialViewToString("MyPartialView", que);
return Json(partialViewString, JsonRequestBehavior.AllowGet);
}
You may need to modify the above statement to fit your uses, but it should get you close.
4) Inject Partial View into Page on AJAX Success
Now, we've setup a Partial View to handle the model data that we want to update. We've updated our view to load from the Partial View by default. We've implemented a controller interface that will let use render that Partial View to a string so that we can inject it into our page. Now, we just need to do that injection.
First, wrap the previous setup #Html.RenderPartial() statement in a div. Let's give it the ID partialViewDiv. This will let us easily target it with jQuery.
$(document).ready(function () {
$("#ID").on("change", function () {
var selectedId = this.value;
var url = "/Sample/getDataBySelectedID";
var $partialViewDiv = $('#partialViewDiv');
$.ajax({
method: "POST",
dataType: "json",
url: url,
data: {
selectedId: selectedId
}
})
.done(function (response, status, jqxhr) {
$partialViewDiv.html(response);
// Do any other updates here.
})
.fail(function (reponse, status, error) {
$partialViewDiv.html('');
// Handle your error here.
});
});
});
Again, these is mostly pseudo-code so you may have to make some modifications. But, at this point, you should be roughly where you need to be. The AJAX call should update your view by reloading the partial view with your new model data.
Tips
Loading a partial view like this may break some jQuery event handlers, depending on your application. If that happens, take a look at this.
You can return any string from the Controller with your AJAX call. You could, if needed, return different partial views than what you originally loaded. Just use the methods from the interface and you can render whatever you need.
The above code is only some general guidelines. Without knowing your full implementation, I can't provide 100% working, bug free code. But, post here if you have any issues and I'll try to help.
A solution i see is with php
location.reload();
That is how you reload but if you want to reload with data you could use something like
window.location.replace("PathToThePage.php?YourDataName=YourData");

How do I populate a list field in a model from javascript?

I have a Kendo.MVC project. The view has a model with a field of type List<>. I want to populate the List from a Javascript function. I've tried several ways, but can't get it working. Can someone explain what I'm doing wrong?
So here is my model:
public class Dashboard
{
public List<Note> ListNotes { get; set; }
}
I use the ListNotes on the view like this:
foreach (Note note in Model.ListNotes)
{
#Html.Raw(note.NoteText)
}
This works if I populate Model.ListNotes in the controller when the view starts...
public ActionResult DashBoard(string xsr, string vst)
{
var notes = rep.GetNotesByCompanyID(user.ResID, 7, 7);
List<Koorsen.Models.Note> listNotes = new List<Koorsen.Models.Note>();
Dashboard employee = new Dashboard
{
ResID = intUser,
Type = intType,
FirstName = user.FirstName,
LastName = user.LastName,
ListNotes = listNotes
};
return View(employee);
}
... but I need to populate ListNotes in a Javascript after a user action.
Here is my javascript to make an ajax call to populate ListNotes:
function getReminders(e)
{
var userID = '#ViewBag.CurrUser';
$.ajax({
url: "/api/WoApi/GetReminders/" + userID,
dataType: "json",
type: "GET",
success: function (notes)
{
// Need to assign notes to Model.ListNotes here
}
});
}
Here's the method it calls with the ajax call. I've confirmed ListNotes does have the values I want; it is not empty.
public List<Koorsen.Models.Note> GetReminders(int id)
{
var notes = rep.GetNotesByCompanyID(id, 7, 7);
List<Koorsen.Models.Note> listNotes = new List<Koorsen.Models.Note>();
foreach (Koorsen.OpenAccess.Note note in notes)
{
Koorsen.Models.Note newNote = new Koorsen.Models.Note()
{
NoteID = note.NoteID,
CompanyID = note.CompanyID,
LocationID = note.LocationID,
NoteText = note.NoteText,
NoteType = note.NoteType,
InternalNote = note.InternalNote,
NoteDate = note.NoteDate,
Active = note.Active,
AddBy = note.AddBy,
AddDate = note.AddDate,
ModBy = note.ModBy,
ModDate = note.ModDate
};
listNotes.Add(newNote);
}
return listNotes;
}
If ListNotes was a string, I would have added a hidden field and populated it in Javascript. But that didn't work for ListNotes. I didn't get an error, but the text on the screen didn't change.
#Html.HiddenFor(x => x.ListNotes)
...
...
$("#ListNotes").val(notes);
I also tried
#Model.ListNotes = notes; // This threw an unterminated template literal error
document.getElementById('ListNotes').value = notes;
I've even tried refreshing the page after assigning the value:
window.location.reload();
and refreshing the panel bar the code is in
var panelBar = $("#IntroPanelBar").data("kendoPanelBar");
panelBar.reload();
Can someone explain how to get this to work?
I don't know if this will cloud the issue, but the reason I need to populate the model in javascript with an ajax call is because Model.ListNotes is being used in a Kendo Panel Bar control and I don't want Model.ListNotes to have a value until the user expands the panel bar.
Here's the code for the panel bar:
#{
#(Html.Kendo().PanelBar().Name("IntroPanelBar")
.Items(items =>
{
items
.Add()
.Text("View Important Notes and Messages")
.Expanded(false)
.Content(
#<text>
#RenderReminders()
</text>
);
}
)
.Events(e => e
.Expand("getReminders")
)
)
}
Here's the helper than renders the contents:
#helper RenderReminders()
{
if (Model.ListNotes.Count <= 0)
{
#Html.Raw("No Current Messages");
}
else
{
foreach (Note note in Model.ListNotes)
{
#Html.Raw(note.NoteText)
<br />
}
}
}
The panel bar and the helpers work fine if I populate Model.ListNotes in the controller and pass Model to the view. I just can't get it to populate in the javascript after the user expands the panel bar.
Perhaps this will do it for you. I will provide a small working example I believe you can easily extend to meet your needs. I would recommend writing the html by hand instead of using the helper methods such as #html.raw since #html.raw is just a tool to generate html in the end anyways. You can write html manually accomplish what the helper methods do anyway and I think it will be easier for you in this situation. If you write the html correctly it should bind to the model correctly (which means it won't be empty on your post request model) So if you modify that html using javascript correctly, it will bind to your model correctly as well.
Take a look at some of these examples to get a better idea of what I am talking about:
http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
So to answer your question...
You could build a hidden container to hold your list values like this (make sure this container is inside the form):
<div id="ListValues" style="display:none">
</div>
Then put the results your ajax post into a javascript variable (not shown).
Then in javascript do something like this:
$('form').off('submit'); //i do this to prevent duplicate bindings depending on how this page may be rendered futuristically as a safety precaution.
$('form').on('submit', function (e) { //on submit, modify the form data to include the information you want inside of your ListNotes
var data = getAjaxResults(); //data represents your ajax results. You can acquire and format that how you'd like I will use the following as an example format for how you could save the results as JSON data: [{NoteID ="1",CompanyID ="2"}]
let listLength = data.length;
for (let i = 0; i < listLength; i++) {
$('#ListValues').append('<input type="text" name="ListNotes['+i+'].NoteID " value="' + data.NoteID +'" />')
$('#ListValues').append('<input type="text" name="ListNotes['+i+'].CompanyID " value="' + data.CompanyID +'" />')
//for your ajax results, do this for each field on the note object
}
})
That should do it! After you submit your form, it should automatically model bind to you ListNotes! You will be able to inpsect this in your debugger on your post controller action.

Changing current viewModel in .NET MVC application

My View uses the Model like below:
public class ObjectViewModel
{
public int ChosenVariant{ get; set; }
public List<Object> Objects{ get; set; }
}
but on page I am displaying details only of one of Object from the list (whose id is equal ChosenVariant).
On the same page I have radio buttons and each of them is binded to one of the Objects from the list:
#foreach (var obj in Model.Objects)
{
<div class="radio">
#{
var options = new RouteValueDictionary();
options["onchange"] = "UpdatePage()";
if (product.ID == Model.ChosenVariant)
{
options["checked"] = "checked";
}
}
#Html.RadioButtonFor(p => Model.ChosenVariant, #product.ID, options)
</div>
}
My problem is that how I can refresh the Model.ChosenVariant and render once again page without refresh?
My first idea was returning whole Model with new value of Model.ChosenVariant in javascript function (on onchange radio button).
This function will call Post action to a Controler, which return once again whole Model (but with new changed Model.ChosenVariant. Then on done action of this Post call I will use $(panel).html(data); for refresh the page.
Is there any easier way to change the current viewmodel without calling Controller?

Is there any way to call JavaScript in an MVC4 ActionLink for one of the RouteValue parameters?

I have a drop down list (DropDownListFor) and an ActionLink on my page. Basically, the problem I'm having is I'm trying to capture the selected value from my drop down list and passing that into my ActionLink as an ID. Here's my code:
#Html.DropDownListFor(x => x.Capsules, new SelectList(Model.Capsules, "pk", "name", "pk"))
<br />
#Html.ActionLink("Submit", "Create",
new { controller = "Process", id = /*JavaScript here to get the selected ID for the DropDownList above*/ },
new { data_role = "button" })
For what I'm trying to accomplish, is there a way to embed JavaScript into my Html.ActionLink call? If there's not a way, or if it's not recommended, could you please advise of another solution to solve this problem? Thanks in advance!
You can do this via intercepting the link using javascript Darin has posted an example of this.
However, it looks like you're trying to submit some values using an ActionLink, and you're probably better off creating a viewmodel which holds all the values you want, and then posting everything using a submit button. This allows you to post more data than just the ID, prevents you from being dependent on Javascript, and keeps all of the code server side instead of mixing and matching.
Judging by the small code you've posted - you already have a model, probably some strongly typed entity, and it has a property called Capsules.
In your controller, create the view model which holds the view's data:
public class YourViewModel
{
YourModel YourModel { get; set; }
public int CapsuleId { get; set; }
}
Then your view:
#using( #Html.BeginForm( "Create", "Process" ) )
{
#Html.DropDownListFor(m=> m.CapsuleId, new SelectList(Model.YourModel.Capsules, "pk", "name", "pk"))
<input type="submit">
}
Then your controller action to handle this:
[HttpPost]
public ActionResult Create( YourViewModel model )
{
var id = model.CapsuleId;
// do what you're going to do with the id
return View();
}
You can put dummy value for the id parameter like this :
#Html.ActionLink("Submit", "Create",
new { controller = "Process", id = "dummy" },
new { data_role = "button" })
Then replace that value when the link is clicked.
// Assuming your link's id is `submit`, and the dropdown's id is `capsules`
$('#submit').click(function() {
var id = $('capsules').val();
$(this).href = $(this).href.replace('dummy', id);
});

Asp.net mvc passing a C# object to Javascript

I have c# class say options more like AjaxOptions.
public class options
{
public string Url {get;set;}
public string httpMethod {get;set}
}
and a javascript function like this
function dosomething(obj)
{
if (obj.Url!="" and obj.HttpMethod=="something")
loadsomething();
}
Now in my Controller action
public class mycontroller : controller
{
public ActionResult WhatToDo()
{
options obj = new options{Url="someurl"};
return PartialView(obj);
}
}
in my view I need this object kind of string which i should be able to pass to my method.
#model options
<script>
dosomething(#model.SomeFunctionToConverToString())
</script>
So I need this SomeFunctionToConverToString method which i will convert this object to string.
Thanks
You should be able to use it like you would any other output of a model property in your view. Just reference the property that you want to pass in the JS function.
#model options
<script>
dosomething('#(model.Url)');
</script>
See this post for more information on using Razor inside of JS
EDIT - Something that might catch you is that if your URL get's broken from the HTML encoding that Razor does using the above, you can use the #Html.Raw() function which will pass the Url property without HTML encoding it.
<script>
dosomething('#Html.Raw(model.Url)');
</script>
EDIT 2 - And another SO post to the rescue! You are going to most likely want to convert your model to JSON in order to use in a Javascript function. So...in order to do that - you will need something in your view model to handle a JSON object.
public class optionsViewModel
{
public options Options{get;set;}
public string JsonData{get;set;}
}
and in your controller:
public class mycontroller : controller
{
public ActionResult WhatToDo()
{
options obj = new options{Url="someurl"};
var myViewModel = new optionsViewModel;
myViewModel.options = obj;
var serializer = new JavaScriptSerializer();
myViewModel.JsonData = serializer.Serialize(data);
return PartialView(myViewModel);
}
}
And finally the view:
#model optionsViewModel
<script>
dosomething('#model.JsonData')
</script>
Using this method, then your function will work as expected:
function dosomething(obj)
{
if (obj.Url!="" and obj.HttpMethod=="something")
loadsomething();
}
EDIT 3 Potentially the simplest way yet? Same premise as edit 2, however this is using the View to JsonEncode the model. There are probably some good arguments on either side whether this should be done in the view, controller, or repository/service layer. However, for doing the conversion in the view...
#model options
<script>
dosomething('#Html.Raw(Json.Encode(Model))');
</script>
Try this:
<script type="text/javascript">
var obj= #Html.Raw(Json.Encode(Model));
function dosomething(obj){}
</script>
That's work for me
Client side:
function GoWild(jsonData)
{
alert(jsonData);
}
Alert print :
{"wildDetails":{"Name":"Al","Id":1}}
MVC Razor Side:
#{var serializer new System.Web.Script.Serialization.JavaScriptSerializer();}
<div onclick="GoWild('#serializer.Serialize(Model.wildDetails)')"> Serialize It </div>
there is also a syntax error
<script type="text/javascript">
dosomething("#Model.Stringify()");
</script>
note the quotes around #Model.Stringify() are for javascript, so the emitted HTML will be:
<script type="text/javascript">
dosomething("this model has been stringified!");
</script>
I would recommend you have a look at SignalR, it allows for server triggered javascript callbacks.
See Scott H site for details: http://www.hanselman.com/blog/AsynchronousScalableWebApplicationsWithRealtimePersistentLongrunningConnectionsWithSignalR.aspx
In summary thou ...
Javascript Client:
var chat = $.connection.chat;
chat.name = prompt("What's your name?", "");
chat.receive = function(name, message){
$("#messages").append("
"+name+": "+message);
}
$("#send-button").click(function(){
chat.distribute($("#text-input").val());
});
Server:
public class Chat : Hub {
public void Distribute(string message) {
Clients.receive(Caller.name, message);
}
}
So .. Clients.receive in C# ends up triggering the chat.receive function in javascript.
It's also available via NuGet.

Categories