Hello,
I have a grid on a partial view which is loaded through jquery/json. The delete is handled through the grid with jquery/json. Previously I was posting the partial view to do the add and then reload the grid. Now I need a button on the partial view that does the add for the grid but does not submit the whole partial view. I have it working by passing the data through variables but I would like to pass the view model instead. Is there a way to do this through jquery?
Here is my current code:
Partial View:
Controller:
I would like to do this just by passing the view model but I don't know if this is possible.
Thanks,
Steve
I have a grid on a partial view which is loaded through jquery/json. The delete is handled through the grid with jquery/json. Previously I was posting the partial view to do the add and then reload the grid. Now I need a button on the partial view that does the add for the grid but does not submit the whole partial view. I have it working by passing the data through variables but I would like to pass the view model instead. Is there a way to do this through jquery?
Here is my current code:
Partial View:
@model PASS.ViewModels.Proposals.RequiredViewModel
@
using
(Ajax.BeginForm(
"_Required"
,
"Proposals"
,
new
AjaxOptions { UpdateTargetId =
"requiredReturnMsg"
, HttpMethod =
"Post"
, OnComplete=
"onDataUpdated()"
}))
{
@Html.HiddenFor(model => model.Proposal_ID, Model.Proposal_ID)
<div
class
=
"editor-container"
>
<div
class
=
"proposal-info"
>
<p>User Facility: @Html.DisplayFor(model => model.User_Facility_ID)</p>
<p>Proposal Type: @Html.DisplayFor(model => model.Proposal_Type)</p>
<p>Proposal ID: @Html.DisplayFor(model => model.Proposal_ID)</p>
</div>
<br
class
=
"clear"
/>
<div
class
=
"editor-label"
>
@Html.Label(
"Primary Field of Research:"
)
</div>
<div
class
=
"editor-field"
>
@Html.DropDownListFor(model => model.Research_Field_ID,
new
SelectList(Model.ResearchFields,
"Value"
,
"Text"
),
"(Select One)"
)
@Html.ValidationMessageFor(model => model.Research_Field_ID)
</div>
<br
class
=
"clear"
/>
<br />
<br />
<div
class
=
"editor-label"
>
@Html.Label(
"Funding Source"
)
</div>
<div
class
=
"editor-field"
>
@Html.DropDownListFor(model => model.Funding_Source_ID,
new
SelectList(Model.FundingSources,
"Value"
,
"Text"
),
"(Select One)"
)
@Html.ValidationMessageFor(model => model.Funding_Source_ID)
<input type=
"button"
id=
"AddFundingSource"
value=
"Add Funding Source"
/>
</div>
<br
class
=
"clear"
/>
<div
class
=
"editor-label"
>
@Html.Label(
"Specify (only if requested)"
)
</div>
<div
class
=
"editor-field"
>
@Html.TextBoxFor(model => model.Funding_Specify,
new
{ style =
"width: 350px;"
})
@Html.ValidationMessageFor(model => model.Funding_Specify)
</div>
<br
class
=
"clear"
/>
<br />
<br />
<p><input type=
"submit"
value=
"Save"
/></p>
<br />
<br />
@(Html.Kendo().Grid<PASS.ViewModels.Proposals.FundingSourcesViewModel>()
.Name(
"gridFundingSources"
)
.Columns(columns =>
{
columns.Bound(o => o.FundingSourceDescription).Title(
"Funding Source"
);
columns.Bound(o => o.Funding_Specify).Title(
"Specifics"
);
columns.Command(command => { command.Destroy(); }).Width(90);
})
.Sortable()
.DataSource(dataSource => dataSource
.Ajax()
.Model(model => model.Id(o => o.ID))
.Read(read => read.Action(
"GetFundingSources"
,
"Proposals"
,
new
{proposalID = Model.Proposal_ID}))
.Destroy(destroy => destroy.Action(
"DeleteFundingSource"
,
"Proposals"
))
)
)
<br />
<br />
<div id=
"requiredReturnMsg"
></div>
</div>
}
<script type=
"text/javascript"
>
$(document).ready(function () {
$(
"#AddFundingSource"
).click(function () {
var proposalID = $(
"#Proposal_ID"
).val();
var fundingSourceID = $(
"#Funding_Source_ID"
).val();
var fundingSpecify = $(
"#Funding_Specify"
).val();
$.post(
'/Proposals/AddFundingSource'
, { proposalID: proposalID, fundingSourceID: fundingSourceID, fundingSpecify: fundingSpecify }, function (data) {
onDataUpdated();
});
});
});
function onDataUpdated() {
var grid = $(
"#gridFundingSources"
).data(
"kendoGrid"
);
grid.dataSource.read();
}
</script>
Controller:
[HttpPost]
public
ActionResult AddFundingSource([DataSourceRequest]DataSourceRequest request, FundingSourcesViewModel vm,
int
proposalID,
int
fundingSourceID,
string
fundingSpecify)
{
using
(var context =
new
PASSEntities())
{
var model =
new
Proposal_Funding_Sources()
{
Proposal_ID = proposalID,
Funding_Source_ID = fundingSourceID,
Funding_Specify = fundingSpecify
};
context.Proposal_Funding_Sources.Add(model);
context.SaveChanges();
}
return
Json(
new
[] { vm }.ToDataSourceResult(request));
}
I would like to do this just by passing the view model but I don't know if this is possible.
Thanks,
Steve
11 Answers, 1 is accepted
0
Hello Stephen,
I am not sure I understand you question correctly, however I would recommend the following approach:
For example:
This should properly populate the DataSourceRequest and bind the new row data to the FundingSourcesViewModel vm parameter.
Regards,
Alexander Popov
Telerik
I am not sure I understand you question correctly, however I would recommend the following approach:
- Set up the Create method of the Grid's DataSource
- Once the Add button is clicked use the insert method to add a new row to the Grid
- Call the sync method to send the new row to the AddFundingSource action method
For example:
.DataSource(dataSource => dataSource
.Ajax()
.Model(model => model.Id(o => o.ID))
.Read(read => read.Action(
"GetFundingSources"
,
"Proposals"
,
new
{proposalID = Model.Proposal_ID}))
.Create(read => read.Action(
"AddFundingSource"
,
"Proposals"
))
.Destroy(destroy => destroy.Action(
"DeleteFundingSource"
,
"Proposals"
))
)
$(
"#AddFundingSource"
).click(
function
() {
var
proposalID = $(
"#Proposal_ID"
).val();
var
fundingSourceID = $(
"#Funding_Source_ID"
).val();
var
fundingSpecify = $(
"#Funding_Specify"
).val();
var
grid = $(
"#gridFundingSources"
).data(
"kendoGrid"
);
grid.dataSource.insert({Proposal_ID: proposalID, Funding_Source_ID: fundingSourceID, Funding_Specify:, fundingSpecify}, 0);
grid.dataSource.sync();
});
public ActionResult AddFundingSource([DataSourceRequest]DataSourceRequest request, FundingSourcesViewModel vm)
Regards,
Alexander Popov
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Stephen
Top achievements
Rank 1
answered on 18 Mar 2014, 02:31 PM
Hello,
Thank you for the response. This is doing what I was hoping for with one exception...
It does add the data to the view model and when it posts to the method it does add it successfully, but when the button is clicked it adds an empty row to the grid but the data itself doesn't show in that row until I refresh the page.
I tried adding: grid.dataSource.read(); after your grid.dataSource.sync(); call but that makes it worse because then it doesn't even show the new empty row added to the grid.
Am I missing something?
Thank you for the response. This is doing what I was hoping for with one exception...
It does add the data to the view model and when it posts to the method it does add it successfully, but when the button is clicked it adds an empty row to the grid but the data itself doesn't show in that row until I refresh the page.
I tried adding: grid.dataSource.read(); after your grid.dataSource.sync(); call but that makes it worse because then it doesn't even show the new empty row added to the grid.
Am I missing something?
0
Hi Stephen,
This behavior is a bit strange and I am not sure what is causing it. Basically the Grid immediately reflects all changes in its DataSource, so adding a new item through the insert method should create a new row in the Grid and how the respective value. Could you please check this screencast and let me know how this differs from your case?
Regards,
Alexander Popov
Telerik
This behavior is a bit strange and I am not sure what is causing it. Basically the Grid immediately reflects all changes in its DataSource, so adding a new item through the insert method should create a new row in the Grid and how the respective value. Could you please check this screencast and let me know how this differs from your case?
Regards,
Alexander Popov
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Stephen
Top achievements
Rank 1
answered on 20 Mar 2014, 01:42 PM
Ok I see what the difference is and I tested to verify.
Only one of the columns I am displaying in my grid is a parameter that is passed to the insert method. My grid is displaying the description that is related to the ID that is added. Here is the column that actually displays the Funding Source that was added:
columns.Bound(o => o.FundingSourceDescription).Title("Funding Source");
I also show the Funding Specify:
columns.Bound(o => o.Funding_Specify).Title("Specifics");
If I do a specify then the row shows at least that column filled but the other doesn't fill because I believe it needs my Get method in order to fill it. That FundingSourceDescription is not one of the parameters sent. The ID is sent and in my Get method when I build my viewmodel I define that description.
So it seems like I need to also call the get method again in order to populate that column. Is this possible?
Only one of the columns I am displaying in my grid is a parameter that is passed to the insert method. My grid is displaying the description that is related to the ID that is added. Here is the column that actually displays the Funding Source that was added:
columns.Bound(o => o.FundingSourceDescription).Title("Funding Source");
I also show the Funding Specify:
columns.Bound(o => o.Funding_Specify).Title("Specifics");
If I do a specify then the row shows at least that column filled but the other doesn't fill because I believe it needs my Get method in order to fill it. That FundingSourceDescription is not one of the parameters sent. The ID is sent and in my Get method when I build my viewmodel I define that description.
public
ActionResult GetFundingSources(
int
proposalID, [DataSourceRequest]DataSourceRequest request)
{
using
(var context =
new
PASSEntities())
{
var vm = (from a
in
context.Proposal_Funding_Sources
join b
in
context.Funding_Sources on a.Funding_Source_ID equals b.ID
where a.Proposal_ID == proposalID
select
new
FundingSourcesViewModel()
{
ID = a.ID,
Proposal_ID = a.Proposal_ID,
Funding_Source_ID = a.Funding_Source_ID,
Funding_Specify = a.Funding_Specify,
FundingSourceDescription = b.Description
});
DataSourceResult result = vm.ToDataSourceResult(request);
return
Json(result, JsonRequestBehavior.AllowGet);
}
}
So it seems like I need to also call the get method again in order to populate that column. Is this possible?
0
Hi Stephen,
Yes, you could make an ajax request and pass the ID to the GetFundingSources method. Once the request's success event is triggered use the response data as parameters for the insert method.
Regards,
Alexander Popov
Telerik
Yes, you could make an ajax request and pass the ID to the GetFundingSources method. Once the request's success event is triggered use the response data as parameters for the insert method.
Regards,
Alexander Popov
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Stephen
Top achievements
Rank 1
answered on 25 Mar 2014, 01:59 PM
Hi,
Ok so now I'm not quite sure I understand. Don't I need the insert method in order to do the insert with the viewmodel? That was what your original answer was providing. So wouldn't I be doing the GetFundingSources after the insert? Not doing the insert on success of the GetFundingSources?
I tried calling GetFundingSources after the insert but that doesn't seem to work. Does the grid.dataSource.insert have a success event?
Thanks,
Steve
Ok so now I'm not quite sure I understand. Don't I need the insert method in order to do the insert with the viewmodel? That was what your original answer was providing. So wouldn't I be doing the GetFundingSources after the insert? Not doing the insert on success of the GetFundingSources?
I tried calling GetFundingSources after the insert but that doesn't seem to work. Does the grid.dataSource.insert have a success event?
Thanks,
Steve
0
Hello again Steve,
I apologize for the misleading response. Please, let me know if my understanding is correct:
I would also ask you to provide a runnable sample project so we can reproduce the issue locally and advise you further. If that is not possible, sharing all related views, models and controllers would also be of help.
Regards,
Alexander Popov
Telerik
I apologize for the misleading response. Please, let me know if my understanding is correct:
- Users are populating some of the item's fields
- The item is then sent to the server, where the rest of the fields are populated and the item is saved
- The server populated fields are not displayed on the Grid until the page is refreshed, even if the dataSource read method is called
I would also ask you to provide a runnable sample project so we can reproduce the issue locally and advise you further. If that is not possible, sharing all related views, models and controllers would also be of help.
Regards,
Alexander Popov
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Stephen
Top achievements
Rank 1
answered on 01 Apr 2014, 03:10 PM
Hi Alexander,
That is not exactly right. All of the necessary data is populated through the form fields. It is sent to the server and then onComplete of the ajax form, I call the grid.dataSource.read. The reason I do this is because the grid is showing a nice description instead of the id that the form field populates. I can't put together a sample project at the moment but here is all of the code.
Partialview:
The commented out code above is what you provided. I am trying to replace my post call sending the variables with sending the ViewModel instead.
Controller:
ViewModel:
That is not exactly right. All of the necessary data is populated through the form fields. It is sent to the server and then onComplete of the ajax form, I call the grid.dataSource.read. The reason I do this is because the grid is showing a nice description instead of the id that the form field populates. I can't put together a sample project at the moment but here is all of the code.
Partialview:
@model PASS.ViewModels.Proposals.RequiredViewModel
@using (Ajax.BeginForm("_Required", "Proposals", new AjaxOptions { UpdateTargetId = "requiredReturnMsg", HttpMethod = "Post", OnComplete="onDataUpdated()" }))
{
@Html.HiddenFor(model => model.Proposal_ID, Model.Proposal_ID)
@Html.HiddenFor(model => model.Proposal_Research_Field_ID, Model.Proposal_Research_Field_ID)
<
div
class
=
"editor-container"
>
<
div
class
=
"editor-label"
>
@Html.Label("Please choose the most appropriate Proposal Review Panel:")
</
div
>
<
div
class
=
"editor-field"
>
@Html.DropDownListFor(model => model.PRP_ID, new SelectList(Model.PRPs, "Value", "Text"), "(Select One)")
@Html.ValidationMessageFor(model => model.PRP_ID)
</
div
>
<
br
class
=
"clear"
/>
<
br
/>
<
div
class
=
"editor-label"
>
@Html.Label("Primary Field of Research:")
</
div
>
<
div
class
=
"editor-field"
>
@Html.DropDownListFor(model => model.Research_Field_ID, new SelectList(Model.ResearchFields, "Value", "Text"), "(Select One)")
@Html.ValidationMessageFor(model => model.Research_Field_ID)
</
div
>
<
br
class
=
"clear"
/>
<
br
/>
<
div
class
=
"editor-label"
>
@Html.Label("Funding Source:")
</
div
>
<
div
class
=
"editor-field"
>
@Html.DropDownListFor(model => model.Funding_Source_ID, new SelectList(Model.FundingSources, "Value", "Text"), "(Select One)")
@Html.ValidationMessageFor(model => model.Funding_Source_ID)
<
input
type
=
"button"
id
=
"AddFundingSource"
value
=
"Add Funding Source"
/>
</
div
>
<
br
class
=
"clear"
/>
<
br
/>
<
div
class
=
"other-specify"
>
<
div
class
=
"editor-label"
>
@Html.Label("Specify")
</
div
>
<
div
class
=
"editor-field"
>
@Html.TextBoxFor(model => model.Funding_Specify, new { style = "width: 350px;" })
@Html.ValidationMessageFor(model => model.Funding_Specify)
</
div
>
<
br
class
=
"clear"
/>
<
br
/>
</
div
>
<
br
/>
<
br
/>
@(Html.Kendo().Grid<
PASS.ViewModels.Proposals.FundingSourcesViewModel
>()
.Name("gridFundingSources")
.Columns(columns =>
{
columns.Bound(o => o.FundingSourceDescription).Title("Funding Source");
columns.Bound(o => o.Funding_Specify).Title("Specifics");
columns.Command(command => { command.Destroy(); }).Width(90);
})
.Sortable()
.DataSource(dataSource => dataSource
.Ajax()
.Model(model => model.Id(o => o.ID))
.Read(read => read.Action("GetFundingSources", "Proposals", new {proposalID = Model.Proposal_ID}))
.Create(create => create.Action("AddFundingSource", "Proposals"))
.Destroy(destroy => destroy.Action("DeleteFundingSource", "Proposals"))
)
)
<
br
/>
<
br
/>
<
p
><
input
type
=
"submit"
value
=
"Save"
/></
p
>
<
br
/>
<
br
/>
<
div
id
=
"requiredReturnMsg"
></
div
>
</
div
>
}
<
script
type
=
"text/javascript"
>
$(document).ready(function () {
$("#Funding_Source_ID").change(function () {
var fundingSourceID = $("#Funding_Source_ID").val();
$.post('/Proposals/GetFundingSourceSpecify', { fundingSourceID: fundingSourceID }, function (data) {
if (data == 'Y') {
$(".other-specify").css('display', 'block');
}
});
});
$("#AddFundingSource").click(function () {
var proposalID = $("#Proposal_ID").val();
var fundingSourceID = $("#Funding_Source_ID").val();
var fundingSpecify = $("#Funding_Specify").val();
/*
var grid = $("#gridFundingSources").data("kendoGrid");
grid.dataSource.insert({Proposal_ID: proposalID, Funding_Source_ID: fundingSourceID, Funding_Specify: fundingSpecify}, 0);
grid.dataSource.sync();
*/
$.post('/Proposals/AddFundingSource', { proposalID: proposalID, fundingSourceID: fundingSourceID, fundingSpecify: fundingSpecify }, function (data) {
onDataUpdated();
});
});
});
function onDataUpdated() {
var grid = $("#gridFundingSources").data("kendoGrid");
grid.dataSource.read();
}
</
script
>
The commented out code above is what you provided. I am trying to replace my post call sending the variables with sending the ViewModel instead.
Controller:
[HttpPost]
public
ActionResult AddFundingSource([DataSourceRequest]DataSourceRequest request, FundingSourcesViewModel vm,
int
proposalID,
int
fundingSourceID,
string
fundingSpecify)
{
using
(var context =
new
PASSEntities())
{
var model =
new
Proposal_Funding_Sources()
{
Proposal_ID = proposalID,
Funding_Source_ID = fundingSourceID,
Funding_Specify = fundingSpecify
};
context.Proposal_Funding_Sources.Add(model);
context.SaveChanges();
}
return
Json(
new
[] { vm }.ToDataSourceResult(request));
}
/*
[HttpPost]
public ActionResult AddFundingSource([DataSourceRequest]DataSourceRequest request, FundingSourcesViewModel vm)
{
using (var context = new PASSEntities())
{
var model = new Proposal_Funding_Sources()
{
Proposal_ID = vm.Proposal_ID,
Funding_Source_ID = vm.Funding_Source_ID,
Funding_Specify = vm.Funding_Specify
};
context.Proposal_Funding_Sources.Add(model);
context.SaveChanges();
}
return Json(new[] { vm }.ToDataSourceResult(request));
}
*/
public
ActionResult GetFundingSources(
int
proposalID, [DataSourceRequest]DataSourceRequest request)
{
using
(var context =
new
PASSEntities())
{
var vm = (from a
in
context.Proposal_Funding_Sources
join b
in
context.Funding_Sources on a.Funding_Source_ID equals b.ID
where a.Proposal_ID == proposalID
select
new
FundingSourcesViewModel()
{
ID = a.ID,
Proposal_ID = a.Proposal_ID,
Funding_Source_ID = a.Funding_Source_ID,
Funding_Specify = a.Funding_Specify,
FundingSourceDescription = b.Description
});
DataSourceResult result = vm.ToDataSourceResult(request);
return
Json(result, JsonRequestBehavior.AllowGet);
}
}
public
JsonResult GetFundingSourceSpecify(
int
fundingSourceID)
{
var context =
new
PASSEntities();
string
specify = (from a
in
context.Funding_Sources where a.ID == fundingSourceID select a.Require_Specific).SingleOrDefault();
return
Json(specify);
}
[HttpPost]
public
ActionResult DeleteFundingSource([DataSourceRequest]DataSourceRequest request, FundingSourcesViewModel vm)
{
using
(var context =
new
PASSEntities())
{
var model =
new
Proposal_Funding_Sources()
{
ID = vm.ID,
Proposal_ID = vm.Proposal_ID,
Funding_Source_ID = vm.Funding_Source_ID,
Funding_Specify = vm.Funding_Specify
};
context.Proposal_Funding_Sources.Attach(model);
context.Proposal_Funding_Sources.Remove(model);
context.SaveChanges();
}
return
Json(
new
[] { vm }.ToDataSourceResult(request));
}
ViewModel:
using
System;
using
System.Collections.Generic;
using
System.ComponentModel.DataAnnotations;
using
System.Linq;
using
System.Web;
using
System.Web.Mvc;
namespace
PASS.ViewModels.Proposals
{
public
class
FundingSourcesViewModel
{
public
int
ID {
get
;
set
; }
public
int
Proposal_ID {
get
;
set
; }
public
int
Funding_Source_ID {
get
;
set
; }
public
string
Funding_Specify {
get
;
set
; }
public
string
FundingSourceDescription {
get
;
set
; }
}
}
0
Hi Stephen,
You can send an object that has the same properties as the FundingSourcesViewModel, so that the AddFundingSource method would bind its "vm" parameter to it. For example:
Regards,
Alexander Popov
Telerik
You can send an object that has the same properties as the FundingSourcesViewModel, so that the AddFundingSource method would bind its "vm" parameter to it. For example:
$.post(
'/Proposals/AddFundingSource'
, {
vm: {
Proposal_ID: proposalID,
Funding_Source_ID: fundingSourceID,
Funding_Specify: fundingSpecify
}
},
function
(data) {
onDataUpdated();
});
[HttpPost]
public
ActionResult AddFundingSource([DataSourceRequest]DataSourceRequest request, FundingSourcesViewModel vm)
{
...
}
Regards,
Alexander Popov
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Stephen
Top achievements
Rank 1
answered on 03 Apr 2014, 02:57 PM
I didn't realize that was possible...I am a bit of a novice with jquery. Though it didn't work until I specified the datatype as json.
$.post(
'/Proposals/AddFundingSource'
, {
vm: {
Proposal_ID: proposalID,
Funding_Source_ID: fundingSourceID,
Funding_Specify: fundingSpecify
}
},
function
(data) {
onDataUpdated();
},
"json"
);
0
Stephen
Top achievements
Rank 1
answered on 03 Apr 2014, 03:41 PM
I also just realized I didn't even need to create the collection. If I just post it like this:
it knows that these are properties of the ViewModel (since the names match I guess) and it just puts it in to the ViewModel.
$.post(
'/Proposals/AddFundingSource'
, { Proposal_ID: proposalID, Funding_Source_ID: fundingSourceID, Funding_Specify: fundingSpecify },
function
(data) {
onDataUpdated();
});
it knows that these are properties of the ViewModel (since the names match I guess) and it just puts it in to the ViewModel.