Hi,
I am trying to Drag & Drop a data item from grid1 to grid2. The row should not be deleted in grid1.
After dropping the dataitem to grid2 I want to
- call the Create method on the controller
- check, if the operation is allowed (there is a role / right model behind)
- update my model, if allowed
- rollback the change on the grid, if not allowed
I use TileLayout and kendoDraggable / kendoDropTarget.
On the frontend everything looks fine. But in the Create Method of the controller, I receive an empty model.
Any ideas, what I am doing wrong?
The model:
public class SignatureModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Img { get; set; }
}
The controller:
public class LayerDefController : Controller
{
public ActionResult AllObjectTypes_Read([DataSourceRequest] DataSourceRequest request)
{
return Json(GetAllObjectTypes().ToDataSourceResult(request));
}
public ActionResult MyObjectTypes_Read([DataSourceRequest] DataSourceRequest request)
{
var all = GetAllObjectTypes();
var my = all.Where(o => o.Id < 5);
return Json(my.ToDataSourceResult(request));
}
public ActionResult MyObjectTypes_Update([DataSourceRequest] DataSourceRequest request)
{
var all = GetAllObjectTypes();
var my = all.Where(o => o.Id < 5);
return Json(my.ToDataSourceResult(request));
}
[HttpPost]
public IActionResult MyObjectTypes_Create([DataSourceRequest] DataSourceRequest request, SignatureModel model)
{
// update model
//_all.Add(model);
return new StatusCodeResult(200);
}
private IEnumerable<SignatureModel> GetAllObjectTypes()
{
var result = Enumerable.Range(0, 50).Select(i => new SignatureModel
{
Id = i,
Name = "Signature " + i,
});
return result.ToList();
}
}
}
The cshtml:
<script id="sig-img-template" type="text/x-kendo-template">
<div class='sig-img'
style='background-image: url(@Url.Content("~/images/#: Id #.svg"));'></div>
<div class='sig-title'>#: Name #</div>
</script>
<script id="my-sig-template" type="text/x-kendo-tmpl">
<div class="signature">
<img src="@Url.Content("~/images/")#:Id#.svg" alt="#:Name# image" />
<h3>#:Name#</h3>
<p>#:kendo.toString(Id, "c")#</p>
</div>
</script>
<!-- container templates -->
<script id="all-sigtypes-template" type="text/x-kendo-template">
<div id="all-sigs-container" style="height:100%;width:100%;">
@(Html.Kendo().Grid<collact.admin.web.Models.SignatureModel>()
.Name("AllSigsGrid")
.Columns(columns => {
columns.Bound(s => s.Id).Width(50).Title("ID");
columns.Bound(s => s.Name).Width(200);
columns.Bound(s => s.Id).ClientTemplateId("sig-img-template").Title("img");
})
.HtmlAttributes(new { style = "height: 90%;" })
.Navigatable()
.Sortable()
.Groupable()
.Filterable()
.ToolBar(t => t.Search())
.Scrollable()
.Selectable(selectable => selectable
.Mode(GridSelectionMode.Multiple))
.PersistSelection(true)
.Navigatable()
.DataSource(dataSource => dataSource
.Ajax()
.Model(model => model.Id(p => p.Id))
.Read(read => read.Action("AllObjectTypes_Read", "LayerDef"))
)
.ToClientTemplate()
)
</div>
</script>
<script id="my-sigtypes-template" type="text/x-kendo-template">
<div id="my-sigs-container" style="height:100%;width:100%;">
@(Html.Kendo().Grid<collact.admin.web.Models.SignatureModel>()
.Name("MySigsGrid")
.Columns(columns => {
columns.Bound(s => s.Id).ClientTemplateId("my-sig-template").Title("img");
})
.HtmlAttributes(new { style = "height: 90%;" })
.DataSource(dataSource => dataSource
.Ajax()
.Model(m => m.Id(s => s.Id))
.Read(read => read.Action("MyObjectTypes_Read", "LayerDef"))
.Create(c => c.Action("MyObjectTypes_Create", "LayerDef"))
.Update(update => update.Action("MyObjectTypes_Update", "LayerDef"))
.PageSize(15)
)
.Pageable()
.Scrollable()
.ToClientTemplate()
)
</div>
</script>
<div id="tilelayout"></div>
@(Html.Kendo().TileLayout()
.Name("tilelayout")
.Columns(5)
.RowsHeight("500px")
.ColumnsWidth("285px")
.Containers(c => {
c.Add().Header(h => h.Text("Alle verfügbaren Objekttypen")).BodyTemplateId("all-sigtypes-template").ColSpan(2).RowSpan(2);
c.Add().Header(h => h.Text("Ausgewählte Objekttypen")).BodyTemplateId("my-sigtypes-template").ColSpan(1).RowSpan(2);
})
.Resizable()
)
<script>
$(document).ready(function () {
var grid1 = $("#AllSigsGrid").data("kendoGrid");
var grid2 = $("#MySigsGrid").data("kendoGrid");
var dataSource1 = grid1.dataSource;
var dataSource2 = grid2.dataSource;
$(grid1.element).kendoDraggable({
filter: "tr",
hint: function (e) {
var item = $('<div class="k-grid k-widget" style="background-color: DarkOrange; color: black;"><table><tbody><tr>' + e.html() + '</tr></tbody></table></div>');
return item;
},
group: "gridGroup1",
});
try {
grid2.wrapper.kendoDropTarget({
drop: function (e) {
var dataItem = dataSource1.getByUid(e.draggable.currentTarget.data("uid"));
console.log("dataItem: " + dataItem + ", ID = " + dataItem.get("Id"));
grid2.dataSource.add(dataItem);
$.each(grid2.dataSource.data(), function () {
console.log(this.Id);
})
grid2.dataSource.sync();
grid2.refresh();
},
group: "gridGroup1",
});
} catch (err) {
console.log(err);
}
});
</script>
<style>
.sig-img {
display: inline-block;
width: 40px;
height: 40px;
background-size: 40px 44px;
background-position: center center;
vertical-align: middle;
line-height: 41px;
box-shadow: inset 0 0 1px #999, inset 0 0 10px rgba(0,0,0,.2);
}
.sig-title {
display: inline-block;
vertical-align: middle;
line-height: 41px;
padding-left: 10px;
}
.signature {
float: left;
position: relative;
width: 111px;
height: 60px;
margin: 0 5px;
padding: 0;
}
.signature img {
width: 50px;
height: 50px;
}
.signature h3 {
margin: 0;
padding: 3px 5px 0 0;
max-width: 96px;
overflow: hidden;
line-height: 1.1em;
font-size: .9em;
font-weight: normal;
text-transform: uppercase;
color: #999;
}
.signature p {
visibility: hidden;
}
.signature:hover p {
visibility: visible;
position: absolute;
width: 110px;
height: 110px;
top: 0;
margin: 0;
padding: 0;
line-height: 110px;
vertical-align: middle;
text-align: center;
color: #fff;
background-color: rgba(0,0,0,0.75);
transition: background .2s linear, color .2s linear;
-moz-transition: background .2s linear, color .2s linear;
-webkit-transition: background .2s linear, color .2s linear;
-o-transition: background .2s linear, color .2s linear;
}
.placeholder {
border: 1px dashed #ccc;
background-color: #fff;
color: #333;
}
.hint {
opacity: 0.4;
}
</style>
The images are just numbered svg-files.
Can anybody help, please?
Best regards
Christine
Hi Christine,
Reviewing the code I do not se anything obvious that might be causing the issue. Can you verify that the form data submitted to the endpoint contains the necessary model data? Also have you checked for any errors on the developer's console?
thank you for your answer.
The console shows no errors. I didn't manage to find out, why the model is empty.
As the role/right model behind it is quite complicated I changed the drop-function in that way:
- find out id of drop target
- call a method in the controller via ajax with ids of dragged item and drop target
- check if change is allowed for this combination of items
- change model if allowed
- return true or false
- reread the dataSource if the model was changed
- display information to user
BTW: Is a placeholder possible for kendoDropTarget (similar to sortable) ?
Best regards
Christine
It is still not clear to me whether the model is submitted to the remote endpoint when the dataSource fires a request to the endpoint handling creation of items. You can verify this in the network tab. Generally speaking in order for an item to be submitted to the create endpoint the id field will be used to determine if a model instance is new or existing. If the value of the specified field is equal to the default value that is specified through the fields configuration, the model is considered new. Is it possible that the items dropped to the grid are submitted to the update endpoint, in case they already have an id different than the default?
As for the placeholder configuration for the kendoDropTarget - such configuration is not available. Refer to the API section here for available configuration options:
https://docs.telerik.com/kendo-ui/api/javascript/ui/droptarget
https://docs.telerik.com/kendo-ui/api/javascript/ui/droptargetarea
https://docs.telerik.com/kendo-ui/controls/interactivity/draganddrop/overview
If I have a dataitem with id = 0 in the grid I am dropping to, the create method is called with the dataitem belonging to id 0, but not with the dragged item.
If I have no dataitem with id = 0 in the datasource of the grid, the method is not called.
Thanks for the information about the placeholder.
In this case if you need to send the dropped items to the create endpoint I can suggest setting the ID of the dataItem, that is going to be added to the second Grid, to 0.
drop: function (e) {var dataItem = dataSource1.getByUid(e.draggable.currentTarget.data("uid"));
var newItem = dataItem;
newItem.Id = 0;
grid2.dataSource.add(newItem);
grid2.dataSource.sync();
grid2.refresh();
},