I've got a simple context menu that I need to be able wire into a Grid. This context menu needs to allow a user to navigate based on the ID of the grid record it's associated to.
I'm currently trying to pass an HTML Data object, but it doesn't seem to be working as expected.
Does anyone know how to extrapolate the ID?
Here is a self contained example of what I'm trying to achieve.
#model IList<EmployeeModel>
<script>
$(document).ready(function () {
setTimeout(function () {
var menu = $("#adminContextMenu"),
original = menu.clone(true);
original.find(".k-state-active").removeClass("k-state-active");
var initMenu = function () {
menu = $("#adminContextMenu").kendoContextMenu({
orientation: 'vertical',
alignToAnchor: true,
filter: ".adminContextMenu",
showOn: "click",
animation: {
open: {
effects: "fadeIn"
},
duration: 250
},
select: function (e) {
console.log(e);
}
});
};
initMenu();
}, 0);
});
</script>
<ul id="adminContextMenu">
<li>Super Long Context Option One</li>
<li class="k-separator"></li>
<li>Alpha</li>
<li>Bravo</li>
<li>Charlie</li>
</ul>
<div id="clientsDb">
#(Html.Kendo().Grid(Model)
.Name("employeeGrid")
.Columns(columns =>
{
columns.Bound(user => user.FullName);
columns.Bound(user => user.UserGUID)
.Width(40)
.ClientTemplate("<span><img src='" + #Web_Helpers.StratosphereImageUrl("#Pencil_Icon ") + "' Title='Administration' Class='adminContextMenu' Data-Guid='#= UserGUID #' /></span>")
.Title(" ");
})
.HtmlAttributes(new {style = "height: 380px;"})
.Scrollable()
.Groupable()
.Sortable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.DataSource(dataSource => dataSource
.Ajax().ServerOperation(false))
)
</div>
Providing your ClientTemplate has a Data attribute
.ClientTemplate("<span><img src='img/settings.png' Title='Administration' Class='adminContextMenu' Data-Guid='#= UserGUID #' /></span>")
You can get that inside the select method of the kendoContextMenu
select: function (e) {
console.log(e.target.dataset.guid);
}
Related
I am trying to have a grid column layout, (2 columns) inside a single droppable container. The project is for an online menu where you can create a menu item, which goes into a droppable container, then you can drag that onto the menu that will be displayed to the user. So there is currently two columns. However the style of the menu demands two columns. Currently I am assigning different classNames to the mapped columns so I can make one of them grid but its pretty messy. Maybe there is a way I can hardcode the droppable instead of map them and run the map on the lists themselves inside each of the hardcoded droppables? Sorry if this is confusing, it sure is for me.
'results' is API data that is initially mapped into savedItems array where newly created menu items will go. Later on menuItems array will pull from the database as well. Right now just trying to have better styling control over the different droppables.
you can see where im assigning different classNames to the droppable during the mapping and its really not a reliable option.
//drag and drop states
const [state, setState] = useState({
menuItems: {
title: "menuItems",
items: []
},
savedItems: {
title: "savedItems",
items: results
}
})
useEffect(() => {
setState({ ...state, savedItems: { ...state.savedItems, items: results } })
}, [results])
// console.log("state", state)
console.log("dummy data", dummyArry)
// updating title graphql mutation
const [elementId, setElementId] = useState(" ");
const updateTitle = async () => {
//api data
const data = await fetch(`http://localhost:8081/graphql`, {
method: 'POST',
body: JSON.stringify({
query: `
mutation {
updateMenu(menuInput: {_id: ${JSON.stringify(elementId)},title: ${JSON.stringify(inputValue)}}){
title
}
}
`
}),
headers: {
'Content-Type': 'application/json'
}
})
//convert api data to json
const json = await data.json();
}
//drag end function
const handleDragEnd = (data) => {
console.log("from", data.source)
console.log("to", data.destination)
if (!data.destination) {
// console.log("not dropped in droppable")
return
}
if (data.destination.index === data.source.index && data.destination.droppableId === data.source.droppableId) {
// console.log("dropped in same place")
return
}
//create copy of item before removing from state
const itemCopy = { ...state[data.source.droppableId].items[data.source.index] }
setState(prev => {
prev = { ...prev }
//remove from previous items array
prev[data.source.droppableId].items.splice(data.source.index, 1)
//adding new item to array
prev[data.destination.droppableId].items.splice(data.destination.index, 0, itemCopy)
return prev
})
}
const columnClass = [
"menuItems-column",
"savedItems-column"
]
let num = 0
return (
<>
<div className='app'>
{results && <DragDropContext onDragEnd={handleDragEnd}>
{_.map(state, (data, key) => {
return (
<div key={key} className='column'>
<h3>{data.title}</h3>
<Droppable droppableId={key}>
{(provided, snapshot) => {
return (
<div
ref={provided.innerRef}
{...provided.droppableProps}
className={columnClass[num]}
// className="droppable-col"
><span className='class-switch'>{num++}</span>
{data.items.map((el, index) => {
return (
<Draggable key={el._id} index={index} draggableId={el._id}>
{(provided) => {
return (
<div className='element-container'
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<div contentEditable="true">
{el.title}
</div>
</div>
)
}}
</Draggable>
)
})}
{provided.placeholder}
</div>
)
}}
</Droppable>
</div>
)
})}
</DragDropContext>}
</div>
</>
)
}
Everyone, I'm trying to add detailPanel based in a condition, it leaves a space when I hide it like this
Link
And This Code works fine when I provide detail panel
get rowDetailsPanel() {
const { detailPanel, classes } = this.props;
// #Workarround To Hide Details Panel In Case There is No Details Panels Provided
return [
{
tooltip: 'Show Name',
disabled: !detailPanel,
icon: () => <ChevronRightIcon className={!detailPanel && classes.displayNone}/>,
render: rowData => detailPanel(rowData)
},
];
}
Link for working detailPanel,
So what I'm trying to do is when I hide the detailPanel, I want to delete the whole column
Any clue will be appreciated
This should work:
get rowDetailsPanel() {
const { detailPanel, classes } = this.props;
// #Workarround To Hide Details Panel In Case There is No Details Panels Provided
return detailPanel ? [
{
tooltip: 'Show Name',
disabled: !detailPanel,
icon: () => <ChevronRightIcon className={!detailPanel && classes.displayNone}/>,
render: rowData => detailPanel(rowData)
},
] : undefined;
Having issues persisting state in mvc grid when using custom command columns. Here is the grid's wrapper
#(Html.Kendo().Grid < Weighmaster_Web.Data.Entity.Destination > ()
.Name("grid")
.Columns(columns => {
columns.Bound(c => c.Description);
columns.Bound(c => c.CODE);
columns.Command(c => {
if (bUpdate) c.Custom("Edit").Click("editItem");
if (bDelete) c.Custom("Delete").Click("deleteItem");
}).Width(175);
})
.Scrollable()
.Groupable()
.Sortable()
.ToolBar(toolbar => {
if (bCreate) {
toolbar.Create().HtmlAttributes(new {
id = "addDestination"
}).Text("Add Destination");
}
})
.ToolBar(t => t.Excel())
.Excel(excel => excel
.FileName("Destinations.xlsx")
.Filterable(true)
.AllPages(true)
.ProxyURL(Url.Action("Excel_Export_Save", "MaterialTransaction"))
)
.Filterable(filterable => filterable.Extra(false))
.Resizable(resize => resize.Columns(true))
.Reorderable(reorder => reorder.Columns(true))
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.DataSource(dataSource => dataSource
.Ajax()
.Events(events => events.Error("error_handler"))
.Read(read => read.Action("DestinationIndex", "Destination").Type(HttpVerbs.Post))
.Model(model => model.Id(p => p.Id))
.PageSize(20)
.Create(update => update.Action("DestinationSave", "Destination").Type(HttpVerbs.Post)))
)
Here i define a click event handler in the wrapper for both edit and delete buttons. i am using custom commands so that i may define custom edit template.
When you look at the actual jquery for this wrapper , i can see the event handler defined.
Then when you leave the page , this code is ran to save the grid's state in a cookie :
$(window).unload(function () {
var grid = $("#grid").data("kendoGrid");
var dataSource = grid.dataSource;
var state = {
columns: grid.columns,
page: dataSource.page(),
pageSize: dataSource.pageSize(),
sort: dataSource.sort(),
filter: dataSource.filter(),
group: dataSource.group()
};
$.cookie(username + "DestinationGridState", JSON.stringify(state), { expires: 365 });
})
The grid's state is read from cookie in $(document).ready like this :
$(document).ready(function () {
var grid = $("#grid").data("kendoGrid");
var toolbar = $("#grid").find(".k-grid-toolbar").html();
var state = $.cookie(username + "DestinationGridState");
if (state) {
state = JSON.parse(state);
var options = grid.options;
options.columns = state.columns;
options.dataSource.page = state.page;
options.dataSource.pageSize = state.pageSize;
options.dataSource.sort = state.sort;
options.dataSource.filter = state.filter;
options.dataSource.group = state.group;
if (grid) {
grid.destroy();
//grid.wrapper.html("");
}
$("#grid").empty().kendoGrid(options).find(".k-grid-toolbar").html(toolbar);
}
});
After the grid's state is read from the cookie, no click event handler is defined for the custom edit command button. So , i guess my question is; How do i correctly save the state of the grid so that my custom command buttons will retain their event handlers?
As mentioned in the kendo documentation:
JSON.stringify() cannot serialize function references (e.g. event
handlers), so if stringification is used for the retrieved Grid state,
all configuration fields, which represent function references, will be
lost.
I once had the same issue, when I was trying to save the filters values in session. I was doing just like you, but then I realized that I didn't need to restore the columns state. If you remove the row options.columns = state.columns;
the custom command will work just as expected.
Hope it helps.
I had a similar problem. After loading the settings my custom delete button stopped working. This was the solution that I came up with:
Save the original grid options. After parsing the saved settings, restore the original values, in this case the column where my delete buttons was placed.
Hope this helps.
$("#Grid").on("click",
".loadsetting",
function(e) {
var grid = $("#Grid").data("kendoGrid");
var originalOptions = grid.options; // Save original options
e.preventDefault();
var options = localStorage["msettings"];
if (options) {
var parsedOptions = JSON.parse(options);
parsedOptions.toolbar = [
{
template: $("#toolbarTemplate").html()
}
];
// Restore values
parsedOptions.columns[30] = originalOptions.columns[30];
grid.setOptions(parsedOptions);
}
});
i want to get data from json file without using script code!
iam using MVC4 and want to put the code in the .cshtml file, how can i do this?
( Iam using kendo function)
example:
#{
ViewBag.Title = "Home Page";
}
<div class="chart-wrapper">
#(Html.Kendo().Chart()
.Name("chart")
.Title(title => title
.Text("Share of Internet Population Growth, 2007 - 2012")
.Position(ChartTitlePosition.Bottom))
.Legend(legend => legend
.Visible(false)
)
.DataSource(dataSource=>dataSource.Read(read=>read.Url("~/")))
.Events(e => e.SeriesClick("onSeriesHover"))
.Series(series => {
series.Pie(new dynamic[] {
new {category="Asia",value=53.8,color="#9de219"},
new {category="Europe",value=16.1,color="#90cc38"},
new {category="LatinAmerica",value=11.3,color="#068c35"},
new {category="Africa",value=9.6,color="#006634"},
new {category="MiddleEast",value=5.2,color="#004d38"},
new {category="NorthAmerica",value=3.6,color="#033939"}
})
.Labels(labels => labels
.Template("#= category #: #= value#%")
.Background("transparent")
.Visible(true)
.Color("Red")
)
.StartAngle(150);
})
.Tooltip(tooltip => tooltip
.Visible(true)
.Format("{0}%")
)
)
<script>
function onSeriesClick(e) {
alert(kendo.format("Series click :: {0} ({1}): {2}",
e.series.name, e.category, e.value));
}
</script>
</div>
i have use
.DataSource(dataSource=>dataSource.Read(read=>read.Url("~/")))
but not working
Try like this,
Example
View
#(Html.Kendo().Chart<Model.DashboardPieChartModel>()
.Name("PieChartPopup")
.Events(events => events.DataBound("onDataBound"))
.Legend(legend => legend
.Visible(false)
)
.DataSource(ds =>
{
ds.Read(read => read.Action("Read_PieChart", "Dashboard"));
}
)
.Series(series =>
{
series.Pie(
model => model.Percentage,
model => model.Service, null, null
).Labels(labels => labels
.Visible(true)
.Template("${ category } - ${ value }%")
).Overlay(ChartPieSeriesOverlay.None);
})
.Tooltip(tooltip => tooltip
.Visible(true)
.Template("${ category } - ${ value }%")
)
)
Controller
public JsonResult Read_PieChart()
{
//Whatever you do here
return Json(return your data);
}
Read this link: http://demos.kendoui.com/dataviz/pie-charts/remote-data.html
When im trying to export kendo resault into pdf i get this error "Input string was not in a correct format."
here is my code :
#(Html.Kendo().Grid((IEnumerable<A.Models.MyViewModel>)ViewBag.myviewmodelbag) //Bind the grid to ViewBag.Products
.Name("List")
.Columns(columns =>
{
columns.Bound(myviewmodelbag => myviewmodelbag.BaseData.Type);
columns.Bound(myviewmodelbag => myviewmodelbag.BaseData.Title);
})
.Pageable() // Enable paging
.Sortable() // Enable sorting
.Groupable()
.Filterable()
.Events(ev => ev.DataBound("onDataBound"))
.ToolBar(toolBar =>
toolBar.Custom()
.Text("Export To PDF")
.HtmlAttributes(new { id = "export" })
.Url(Url.Action("Export", "MyViewModel", new { page = 1, pageSize = "~", filter = "~", sort = "~" }))
)
<script type="text/javascript">
function onDataBound(e) {
var grid = $('#List').data('kendoGrid');
// ask the parameterMap to create the request object for you
var requestObject = (new kendo.data.transports["aspnetmvc-server"]({ prefix: "" }))
.options.parameterMap({
page: grid.dataSource.page(),
sort: grid.dataSource.sort(),
filter: grid.dataSource.filter()
});
// Get the export link as jQuery object
var $exportLink = $('#export');
// Get its 'href' attribute - the URL where it would navigate to
var href = $exportLink.attr('href');
// Update the 'page' parameter with the grid's current page
href = href.replace(/page=([^&]*)/, 'page=' + requestObject.page || '~');
// Update the 'sort' parameter with the grid's current sort descriptor
href = href.replace(/sort=([^&]*)/, 'sort=' + requestObject.sort || '~');
// Update the 'pageSize' parameter with the grid's current pageSize
href = href.replace(/pageSize=([^&]*)/, 'pageSize=' + grid.dataSource._pageSize);
//update filter descriptor with the filters applied
href = href.replace(/filter=([^&]*)/, 'filter=' + (requestObject.filter || '~'));
// Update the 'href' attribute
$exportLink.attr('href', href);
}
</script>
and my controller is like this :
public FileResult Export([DataSourceRequest]DataSourceRequest request)
{
IEnumerable products = db.AA.ToDataSourceResult(request).Data;
now the problem is if i use exatcly as above i get the error but if hardcode the value like this:
.Url(Url.Action("Export", "MyViewModel", new { page = 1, pageSize = "", filter = "", sort = "" }))
it works without error but the controller only get the page an other value will be null.
also i tried to add "grid_Page , ... " to all of parameter but none works
Ok my bad , i fixed it !
since im using server side to populate the grid , the js event part cant be called :
function onDataBound(e) {
var grid = $('#List').data('kendoGrid');
and after i changed to this :
$(document).ready(function () {
var grid = $('#List').data('kendoGrid');
and removed this line :
.Events(ev => ev.DataBound("onDataBound"))
now it works fine.