I have a GridPanel component in my EXT.NET MVC project, and I would like to create a dynamic tooltip that will display the text/data in each cell when hovered over. Since the .ToolTips() component isn't compatible with this, I am using JavaScript to try to render a dynamic tooltip. My current code creates HTML elements, and then adds tooltips to them:
var el = Ext.getBody().createChild({
html: '<div data-num="1" class="item">Foo</div>' +
'<div data-num="2" class="item">Bar</div>' +
'<div data-num="3" class="item">Baz</div>' +
'<div class="notip">No tip here</div>'
});
new Ext.tip.ToolTip({
target: el,
delegate: '.item',
listeners: {
beforeshow: function (tip) {
var current = tip.currentTarget.dom;
tip.setHtml('Item #' + current.getAttribute('data-num'));
}
}
});
And here is the code for the GridPanel I want to attach it to:
Html.X().GridPanel()
.Title("Request Priorities")
.ID("reqPrioritiesGrid")
.ColumnWidth(1)
.MarginSpec("0 0 0 0")
.Flex(1)
.ToolTips(t => t.Add(Html.X().ToolTip().Html("hello").ID("storeTip").Target("App.storeReqPriorities")))
.Border(true)
.Store(
Html.X().Store()
.ID("storeReqPriorities")
.AutoLoad(true)
.DataSource(Model.RequestPriorities)
.Model(
Html.X().Model()
.Fields(f =>
{
f.Add(Html.X().ModelField().Name("RequestPriorityKey").Type(ModelFieldType.Int));
f.Add(Html.X().ModelField().Name("RequestPriorityName").Type(ModelFieldType.String));
f.Add(Html.X().ModelField().Name("RequestPriorityDescription").Type(ModelFieldType.String));
f.Add(Html.X().ModelField().Name("SortOrder").Type(ModelFieldType.Int));
f.Add(Html.X().ModelField().Name("ResponseTarget").Type(ModelFieldType.String));
f.Add(Html.X().ModelField().Name("ResponseFormat").Type(ModelFieldType.String));
f.Add(Html.X().ModelField().Name("ResponseSLA").Type(ModelFieldType.String));
})
)
.ServerProxy(
Html.X().AjaxProxy()
.Url(Url.Action("ManageLists_GetRequestPriorities", "Admin", new { area = "Cadence" }))
)
)
.Listeners(l =>
{
l.Select.Handler = "handleReqPopulate(record.data);" + "toggleEditRequest();" + "resetAddNew();";
})
.ColumnModel(
Html.X().Column().Flex(1).Text("Request Priority Name").DataIndex("RequestPriorityName"),
Html.X().Column().Flex(3).Text("Request Priority Desciption").DataIndex("RequestPriorityDescription"),
Html.X().Column().Flex(1).Text("Sort Order").DataIndex("SortOrder"),
Html.X().Column().Flex(1).Text("Response Target").DataIndex("ResponseTarget"),
Html.X().Column().Flex(1).Text("Response Format").DataIndex("ResponseFormat"),
Html.X().Column().Flex(1).Text("Response SLA").DataIndex("ResponseSLA")
)
Is there a method similar to .createChild() used in the JavaScript above that can attach a tooltip to an element that is being dynamically created in MVC?
You can bind the ToolTip component to the grid's view with a custom show handler that would fetch the cell data (or row, or entire grid) and show the way you instruct. Wouldn't that suffice for your scenario?
In this case you won't be creating child tooltips though, but rather using the same tooltip to show specific data depending on where you hover the mouse over.
Add this after the grid -- yes, outside it. Given your code snippets, the ToolTip component declaration should look like this:
#(Html.X().ToolTip()
.Target("={App.reqPrioritiesGrid.getView().el}")
.Delegate(".x-grid-cell")
.TrackMouse(true)
.Listeners(l => l.Show.Handler="onShow(this, App.reqPrioritiesGrid)")
)
Then have a handler fill the tooltip's contents like this:
var onShow = function (toolTip, grid) {
var view = grid.getView(),
store = grid.getStore(),
record = view.getRecord(view.findItemByChild(toolTip.triggerElement)),
column = view.getHeaderByCell(toolTip.triggerElement),
data = record.get(column.dataIndex);
toolTip.update(data);
};
From this point, you could further customize the show function to build the tooltip the way you need it.
A grid with a per-cell tooltip is showcased in Ext.NET examples (WebForms) at Miscellaneous > Tooltips > GridPanel Cell Tooltip.
Hope this helps!
Related
I'm use kendo ui grid popup and using code
.Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("tax_manage")
I and use
columns.Command(command => command.Custom("ViewData").Text("ViewData")).Width(60).Title("ViewData");
How to do this?
In my kendo grid Custom button to call "tax_manage" in Views/Shared/EditorTemplates/tax_manage
and show template inner popup with Javascript and when I click Custom Button I need to pass value to popup, such as a string (e.g.: this was called by Custom Button)
I guess you can send the parameter via the corresponding table row. To open the popup, you can use grid's editRow method:
columns.Command(command => command.Custom("ViewData").Text("ViewData").Click("cmdClick"))
...
.Events(events => events.Edit("gridEdit"))
function cmdClick(e) {
var tr = $(e.target).closest("tr"); // get the corresponding table row
var grid = $("#grid").data("kendoGrid");
var dataItem = grid.dataItem(tr); // You may want to use the corresponding data item ...
tr.data("message") = "This was called by Custom Button";
grid.editRow(tr);
}
function gridEdit(e) {
var dataItem = e.model;
var tr = $("#grid").data("kendoGrid").tbody.find("tr[data-uid='" + dataItem.uid + "']");
var message = tr.data("message");
... // do something with the message.
}
I am rendering a component into a grid rowExpander plugin rowBodyTpl:
plugins: [{
ptype: 'rowexpander',
rowBodyTpl : [
'<div id="contact-row-{Id}"> </div>'
]
}],
var row = 'contact-row-' + record.get('Id'),
grid = Ext.getCmp(gridId),
if(!grid) me.createSubGrid(record,gridId).render(row);
This works fine. But when the grid receives an update event for a record with certain modifiedFields, that record's rowExpander is rerendered using the rowTpl only, and the inner grid is dangling somewhere. I can access the grid using Ext.getCmp, and grid.rendered is true, but it is not shown. So I guess I have to reattach the grid after the row has been rerendered.
I think I can attach to the update event, and find out whether the rowTpl has been rerendered without the child grid using
if(!grid.container.contains(grid.el))
But is there a way to put the grid back into the dom?
I have tried
grid.container.insertFirst(grid.el);
but this does not work. The element is inserted but the grid is not displayed.
Any ideas?
The way you are doing leads to memory leaks (because your component is not destroy when the grid is re-render).
I suggest to check at : Component Template (http://skirtlesden.com/ux/ctemplate) or if you try to render a nested grid, there was several attempt to build something correct and I think a working one is the following : http://blogs.walkingtree.in/2015/06/30/nested-grid-in-sencha-ext-js/
With my trials, I already was on the right track, and the error was somewhere else entirely. The problem was that my update event fn which did the reattach was executed before the update event fn that broke everything, because the fn was fired on the same event and had the same priority, but was attached to the store earlier. Changing the priority was one option, but I just put the creation into the boxready event, which is executed after the view has attached its events to the store:
xtype:'grid',
listeners:{
boxready:function(grid) {
var store = grid.getStore();
...
store.on({
update:function(store, record) {
me.restoreSubgridDom(record);
},
beforeload:function(store) {
var records = store.getRange();
Ext.each(records,me.destroySubgrid);
}
});
}
}
with the two functions:
restoreSubgridDom: function(record) {
var row = 'contact-row-' + record.get('Id'),
gridId = 'ContactRow'+record.get('Id')+'Grid',
grid = Ext.getCmp(gridId);
if(grid && !grid.container.contains(grid.el))
{
grid.container.insertFirst(grid.el);
}
},
destroySubgrid: function(record) {
var gridId = 'ContactRow'+record.get('Id')+'Grid',
grid = Ext.getCmp(gridId);
if(grid) grid.destroy();
}
I am using Froala and I am stuck creating a custom drop down with dynamic option sets in it. I have used their common way to create the drop down but that is useless if we have to fetch the values from db.
I want to make a "Templates" dropdown with 10 options to select which will be created dynamically.
Currently we create a custom drop down this way,
options: {
'Template One': function(e){
_this.editable('insertHTML', "<p>This is template one</p>", true);
},
}
I want this to be dynamic, meaning I will fetch the names and content of the templates from database and add them in the option set accordingly.
something like,
options : {
$.each(alltemplates, function(i, h){
i: function(e){ /// "i" will be the name of the template fetched from db
_this.editable('insertHTML', h, true); // h is the html fetched from db
},
})
}
which will create the drop down dynamically. Any help please ?
Expanding on #c23gooey's answer, here's what we came up with for a similar problem (inserting dynamically-generated mail-merge placeholders).
var commandName = 'placeholders',
iconName = commandName + 'Icon',
buildListItem = function (name, value) {
// Depending on prior validation, escaping may be needed here.
return '<li><a class="fr-command" data-cmd="' + commandName +
'" data-param1="' + value + '" title="' + name + '">' +
name + '</a></li>';
};
// Define a global icon (any Font Awesome icon).
$.FroalaEditor.DefineIcon(iconName, { NAME: 'puzzle-piece' });
// Define a global dropdown button for the Froala WYSIWYG HTML editor.
$.FroalaEditor.RegisterCommand(commandName, {
title: 'Placeholders',
type: 'dropdown',
icon: iconName,
options: {},
undo: true,
focus: true,
refreshAfterCallback: true,
callback: function (cmd, val, params) {
var editorInstance = this;
editorInstance.html.insert(val);
},
refreshOnShow: function ($btn, $dropdown) {
var editorInstance = this,
list = $dropdown.find('ul.fr-dropdown-list'),
listItems = '',
placeholders = editorInstance.opts.getPlaceholders();
// access custom function added to froalaOptions on instance
// use a different iteration method if not using Angular
angular.forEach(placeholders, function (placeholder) {
listItems += buildListItem(placeholder.name, placeholder.value);
});
list.empty().append(listItems);
if (!editorInstance.selection.inEditor()) {
// Move cursor position to end.
editorInstance.selection.setAtEnd(editorInstance.$el.get(0));
editorInstance.selection.restore();
}
}
});
We ran this method by Froala support and were told:
The editor doesn't have any builtin mechanism for using dynamic
content when showing the dropdown, but your solution is definitely a
good one.
Use the refreshOnShow function to change the options dynamically.
What i am trying to do is dynamically add container to panel on click of button.
1st instance of container gets added and can be seen in the panel.items.length
2nd instance onwards the panel.items.length doesn't change. but the panel can be seen in dom and on screen.
Just wanted to know why the panel.items.length is not increasing. Is it a bug?
Fiddler link https://fiddle.sencha.com/#fiddle/p3u
Check for the line :
console.log(qitems);
below debugger; it is set to questionsblock.items.length that i am talking about.
Remove the itemId from QuestionTemplate and remove renderTo from the new instance.
Your click handler should look like this:
listeners: {
'click': function(button) {
var questionPanel = button.up('form').down('#questionsblock'),
qitems = questionPanel.items.length,
questiontemplate = Ext.create('QuestionTemplate', {
qid: qitems,
questiontype: 'text'
});
console.log(qitems);
questionPanel.add(questiontemplate);
questionPanel.doLayout();
}
}
Check this fiddle: https://fiddle.sencha.com/#fiddle/p47
I want to add new Row in Kendo Grid which is having Default value in First Cell.
How can I set the Default Value in that added Row of Kendo Grid
I am adding New Row in Kendo Grid as::
$('#AddSingleSuppliment').click(function () {
grid.addRow();
});
But I want to Set the Value of First cell on the Basis of Value of Clicked DOM element, Like
$('#AddSingleSuppliment').click(function () {
var temVal=$(this).text();
grid.addRow(tempVal);
});
But we can't do it in that Manner.
So please help me on this, For adding New Row in Kendo Grid with one Cell having Value of Button clicked.
Now I am able to Add New Row in Kendo Grid as,
$("#AddSingleSupplement").click( function(){
var tempSupplement = $(this).val();
//alert(tempSupplement);
grid.addRow(tempSupplement);
grid.dataSource._data[0].Description = $(this).text().trim();
});
But the Value is not Directly Shown while adding new Row. It is Shown after we click on some other element.
Please Suggest me wether this one is the Correct way to do this or there is any other way than this.
For dynamic defaults you can wire up your logic on Edit event, something like:
<script>
$('#AddSingleSuppliment').click(function () {
grid.addRow();
});
function onEdit(e)
{
//Custom logic to default value
var name = $("#AddSingleSuppliment").text();
// If addition
if (e.model.isNew()) {
//set field
e.model.set("Name", name); // Name: grid field to set
}
}
</script>
As per Kendo team , Default value cannot be changed dynamically.
However, we can make use the Grid edit event to pre-populate the edit form:
edit: function(e) {
if (e.model.isNew() && !e.model.dirty) {
e.container
.find("input[name=ProductName]") // get the input element for the field
.val("MyCustomValue") // set the value
.change(); // trigger change in order to notify the model binding
}
}