reloading dataurl elements in jqGrid - javascript

I have a simple grid with the following options:
jQuery("#mygrid").jqGrid({
url: 'dataurl.htm',
datatype: 'json',
ajaxSelectOptions: { cache: false }
...
colModel: [
{ name: 'foo', index: 'foo', width: 25, stype: 'select', searchoptions:{ sopt:
['eq'], dataUrl: 'someurl.htm?columnName=foo'}}
]
});
However, when I call $("#mygrid").trigger("reloadGrid"); it only loads the data for the table from dataurl.htm but it does not load the data for the foo column from the some url.htm link.
I've read couple of questions like these on SO and it was suggested to have ajaxSelectOptions: { cache: false } but this is not working for me.
The someurl.htm returns <select> <option val=''>something</option></select>

It's absolutely correct question! The current implementation of jqGrid has only toggleToolbar method which can hide the toolbar, but the toolbar itself will be created once. So all properties of the toolbar stay unchanged the whole time.
To fix the problem I wrote small additional method destroyFilterToolbar which is pretty simple:
$.jgrid.extend({
destroyFilterToolbar: function () {
"use strict";
return this.each(function () {
if (!this.ftoolbar) {
return;
}
this.triggerToolbar = null;
this.clearToolbar = null;
this.toggleToolbar = null;
this.ftoolbar = false;
$(this.grid.hDiv).find("table thead tr.ui-search-toolbar").remove();
});
}
});
The demo uses the method. One can recreate searching toolbar after changing of properties of some columns. In the code below one can change the language of some texts from the searching toolbar:
The corresponding code is below:
$("#recreateSearchingToolbar").change(function () {
var language = $(this).val();
// destroy searching toolbar
$grid.jqGrid("destroyFilterToolbar");
// set some searching options
$grid.jqGrid("setColProp", "closed",
language === "de" ?
{searchoptions: {value: ":Beliebig;true:Ja;false:Nein"}} :
{searchoptions: {value: ":Any;true:Yes;false:No"}});
$grid.jqGrid("setColProp", "ship_via",
language === "de" ?
{searchoptions: {value: ":Beliebig;FE:FedEx;TN:TNT;IN:Intim"}} :
{searchoptions: {value: ":Any;FE:FedEx;TN:TNT;IN:Intim"}});
// create new searching toolbar with nes options
$grid.jqGrid("filterToolbar", {stringResult: true, defaultSearch: "cn"});
});

Related

Ext.Defer gives getAsynchronousLoad Error

I've just defined a combobox. Firstly it loads a countrylist and when select a value it's fire a change event which doing a ajax query to DB within searching service;
The thing; this configuration works pretty well when I click and open combobox items. But when I'm typing to combobox's field it's fires listener's store.load and because of none of country selected yet, the search query url gives not found errors of course.
{
xtype: 'countrycombo',
itemId: 'countryName',
name:'country',
afterLabelTextTpl: MyApp.Globals.required,
allowBlank: false,
flex: 1,
// forceSelection: false,
// typeAhead: true,
// typeAheadDelay: 50,
store: {
proxy: {
type: 'ajax',
// isSynchronous: true,
url: MyApp.Globals.getUrl() + '/country/list?limit=250',
// timeout: 300000,
reader: {
type: 'json',
rootProperty: 'data'
}
},
pageSize: 0,
sorters: 'description',
autoLoad: true
}
,
listeners: {
change: function (combo, countryId) {
var cityStore = Ext.getStore('cityCombo');
cityStore.getProxy()
.setUrl(MyAppp.Globals.getUrl() + '/city/view/search?query=countryid:'+ countryId);
// Ext.defer(cityStore.load, 100);
cityStore.load();
}
}
},
I've tried several things as you see in code above to set a delay/timeout for load during typing to combobox text field; Ext.defer, timeoutconfig on proxy, typeAhead config on combo but none of them worked!
I thought that Ext.defer is the best solution but it gives this error:
Uncaught TypeError: me.getAsynchronousLoad is not a function at load (ProxyStore.js?_dc=15169)
How can I set a delay/timeout to combobox to fires load function?
Instead of Ext.defer(cityStore.load, 100);
try using this :
Ext.defer(function(){
cityStore.load
}, 300);
If this doest work, try increasing your delay
or you can put a logic before loading
like this :
if(countryId.length == 5){
cityStore.load
}
This will ensure that you Entered the right values before loading
Hope this helps, and Goodluck on your project
well.. I've tried to implement #Leroy's advice but somehow Ext.defer did not fire cityStore.load. So I keep examine similar situations on google and found Ext.util.DelayedTask
So configured the listerens's change to this and it's works pretty well;
listeners: {
change: function (combo, countryId) {
var alert = new Ext.util.DelayedTask(function () {
Ext.Msg.alert('Info!', 'Please select a country');
});
var cityStore = Ext.getStore('cityCombo');
cityStore.getProxy().setUrl(MyApp.Globals.getUrl() + '/city/view/search?query=countryid:'+ countryId);
if (typeof countryId === 'number') {
cityStore.load();
} else {
alert.delay(8000);
}
}
}

CKEditor's dialog textarea is not editable

So I'm making my own plugin to the ckeditor, since I need a special case. Anyway, I can't make textarea element editable. This is my whole code to my own dialog (for the plugin):
CKEDITOR.dialog.add('myDialog', function(editor) {
return {
title: 'My Plugin',
minWidth: 750,
minHeight: 500,
onShow: function(evt) {
var selection = editor.getSelection();
var widget = editor.widgets.selected[0];
var element = !!widget && !!widget.parts ? widget.parts['my'] : false;
var command = this.getName();
if(command == 'myDialog') {
var code = selection.getSelectedElement();
if(code && !!element) {
this.setupContent(code);
widget.data.myinput = element.getHtml();
}
}
},
contents: [{
id: 'info',
label: 'Info',
accessKey: 'I',
elements: [{
id: 'myinput',
type: 'textarea',
required: true,
label: 'Content',
rows: 42,
setup: function(widget) {
this.setValue(widget.data.myinput);
},
commit: function(widget) {
widget.setData('myinput', this.getValue());
}
}]
}],
};
});
Problem is only within contents.myinput. It type is textarea but when I open the dialog its not editable. When I change type to the text and remove rows, then text input shows up, working great and so on. Only textarea is problem. This is how it looks like after opening the dialog:
Version of my CKEditor is 4.5. I already made 3 plugins before, but never had to use textarea so all other plugins works except this one. I would append jsFiddle, if there was any site offering "ckeditor plugin tester" so I just post my code.
Problem is that I init ckeditor in the bootstrap's dialog. So the solution for my problem is to apply the following lines of code after initialization:
$.fn.modal.Constructor.prototype.enforceFocus = function() {
var $modalElement = this.$element;
$(document).on('focusin.modal', function(e) {
var $parent = $(e.target.parentNode);
if($modalElement[0] !== e.target
&& !$modalElement.has(e.target).length
&& !$parent.hasClass('cke_dialog_ui_input_select')
&& !$parent.hasClass('cke_dialog_ui_input_text')
&& !$parent.hasClass('cke_dialog_ui_input_textarea')) {
$modalElement.focus();
}
})
};
I had this code before the problem, but I was missing !$parent.hasClass('cke_dialog_ui_input_textarea') which I forget to add, so this was my fault :)

Selectize: Setting Default Value in onInitialize with setValue

I have a web application with multiple Selectize objects initialized on the page. I'm trying to have each instance load a default value based on the query string when the page loads, where ?<obj.name>=<KeywordID>. All URL parameters have already been serialized are are a dictionary call that.urlParams.
I know there are other ways to initializing Selectize with a default value I could try; but, I'm curious why calling setValue inside onInitialize isn't working for me because I'm getting any error messages when I run this code.
I'm bundling all this JavaScript with Browserify, but I don't think that's contributing to this problem.
In terms of debugging, I've tried logging this to the console inside onInititalize and found that setValue is up one level in the Function.prototype property, the options property is full of data from load, the key for those objects inside options corresponds to the KeywordID. But when I log getValue(val) to the console, I get an empty string. Is there a way to make this work or am I ignoring something about Selectize or JavaScript?
module.exports = function() {
var that = this;
...
this.selectize = $(this).container.selectize({
valueField: 'KeywordID', // an integer value
create: false,
labelField: 'Name',
searchField: 'Name',
preload: true,
allowEmptyOptions: true,
closeAfterSelect: true,
maxItems: 1,
render: {
option: function(item) {
return that.template(item);
},
},
onInitialize: function() {
var val = parseInt(that.urlParams[that.name], 10); // e.g. 5
this.setValue(val);
},
load: function(query, callback) {
$.ajax({
url: that.url,
type: 'GET',
error: callback,
success: callback
})
}
});
};
...
After sprinkling in some console.logs into Selectize.js, I found that the ajax data hadn't been imported, when the initialize event was triggered. I ended up finding a solution using jQuery.when() to make setValue fire after the data had been loaded, but I still wish I could find a one-function-does-one-thing solution.
module.exports = function() {
var that = this;
...
this.selectize = $(this).container.selectize({
valueField: 'KeywordID', // an integer value
create: false,
labelField: 'Name',
searchField: 'Name',
preload: true,
allowEmptyOptions: true,
closeAfterSelect: true,
maxItems: 1,
render: {
option: function(item) {
return that.template(item);
},
},
load: function(query, callback) {
var self = this;
$.when( $.ajax({
url: that.url,
type: 'GET',
error: callback,
success: callback
}) ).then(function() {
var val = parseInt(that.urlParams[that.name], 10); // e.g. 5
self.setValue(val);
});
}
});
};
...
You just need to add the option before setting it as the value, as this line in addItem will be checking for it:
if (!self.options.hasOwnProperty(value)) return;
inside onInitialize you would do:
var val = that.urlParams[that.name]; //It might work with parseInt, I haven't used integers in selectize options though, only strings.
var opt = {id:val, text:val};
self.addOption(opt);
self.setValue(opt.id);
Instead of using onInitialize you could add a load trigger to the selectize. This will fire after the load has finished and will execute setValue() as expected.
var $select = $(this).container.selectize({
// ...
load: function(query, callback) {
// ...
}
});
var selectize = $select[0].selectize;
selectize.on('load', function(options) {
// ...
selectize.setValue(val);
});
Note that for this you first have to get the selectize instanze ($select[0].selectize).
in my case it need refresh i just added another command beside it
$select[0].selectize.setValue(opt);
i added this
$select[0].selectize.options[opt].selected = true;
and changes applied
but i dont know why?
You can initialize each selectize' selected value by setting the items property. Fetch the value from your querystring then add it as an item of the items property value:
const selectedValue = getQueryStringValue('name') //set your query string value here
$('#sel').selectize({
valueField: 'id',
labelField: 'title',
preload: true,
options: [
{ id: 0, title: 'Item 1' },
{ id: 1, title: 'Item 2' },
],
items: [ selectedValue ],
});
Since it accepts array, you can set multiple selected items

ExtJS property grid reload after render

I have a property grid :
periods.each(function(record){
var tempPropGrid = me.getView().add(
{
xtype:'propertygrid',
width: 80,
header: false,
title: 'prop grid',
//for some reason the headers are not hiding, we may need to deal with this using CSS
//hideHeaders: true,
enableColumnResize: false,
sortableColumns: false,
nameColumnWidth: 1,
source: record.data,
sourceConfig: {
periodScrumMaster: {
editor: Ext.create('Ext.form.ComboBox', {
tdCls: 'red',
store: team,
queryMode: 'local',
displayField: 'personName',
valueField: 'personName',
listeners: {
'expand' : function(combo) {
var gridvalues = this.up('propertygrid').getSource();
combo.getStore().clearFilter(true);
combo.getStore().addFilter({property: 'teamName', value: teamName});
combo.getStore().addFilter({property: 'periodName', value: gridvalues.periodName});
var totalFTE = team.count();
console.log(totalFTE);
var teamStore = Ext.getStore('personPeriods');
console.log('store');
console.log(teamStore);
},
}}),
displayName: 'Scrum Master'
},
},
That has a render listener:
beforerender: function(){
debugger;
var gridValues = this.getSource();
// console.log(record);
//debugger;
// filter periods for this period only
periods.filterBy(function(record,id){
if(record.get("periodName") === gridValues.periodName){
return true;
}});
// filter teamMembers for this period and team
var view = this.up();
var vm = view.getViewModel();
var store = vm.getStore('teamMembers');
store.filterBy(function(record,id){
if(record.get("periodName") === gridValues.periodName) {
return true;
}});
//store.clearFilter(true);
store.addFilter({property: 'teamName', value: teamName});
// get FTEs assigned to this team in this period by counting records
var resourcedFtes = store.count();
// Here I check the record in the periods store to make sure the data matches up with how many resourcedFte there is an update it if required
// This is super bad and will need to refactor
periods.each(function(record,idx){
var value = record.get('resourcedFte');
if(value != resourcedFtes){
record.set('resourcedFte',resourcedFtes);
record.commit();
vm.data.parentController.saveParent();
}});
// Need to call save parent so that the record is updated when we update it above
//Clear everything so that we can start fresh next period
store.clearFilter(true);
//periods.clearFilter(true);
Basically there is some logic to check if the data is correct/up to date and if its not it updates it. This works fine, but the data is not then loaded into the grid. I have to refresh after rendering the grid for it to load correctly.
Is there a way I can call a refresh or reload method on the property grid to load the data again inside an if statement?
If I understand your question, I would suggest you to programm the store proxy so that it returns the whole changed record.
Is your store parametered with autoLoad enabled?
(sorry I can't (yet) comment)

Storing state using 2 instances of the same JQuery plugin

I'm coding a jQuery plugin to build KendoUI grids. Everything was fine until I had to use 2 instances of the plugin in the same page. In this case, I need each instance of the plugin to have its own data.
I've read the jQuery guidelines for storing data with .data(), but when trying to access from outside the code of the plugin to the 'getSelectedItem()' this way:
selectedItemGrid1= $("#Grid1").kendoGrid_extended.getSelectedItem();
selectedItemGrid2= $("#Grid2").kendoGrid_extended.getSelectedItem();
I get the selectedItem of Grid2 in selectedItemGrid1. Here is a simplified version of my plugin code. Basically what I wanted to do is, anytime a row of the grid is selected ("change" event on the kendoGrid definition), store the new selected row inside the plugin, so when the user clicks on a "delete" button, read from the plugin the selected row and call the delete action with the info recovered from the plugin.
$.fn.kendoGrid_extended = function (options) {
var opts = $.extend({}, $.fn.kendoGrid_extended.defaults, options);
opts.controlId = '#' + this.attr('id');
var gridExtended;
var selectedItem;
var instance = $(this);
//Public accessor for the selectedItem object.
$.fn.kendoGrid_extended.getSelectedItem = function () {
return instance.data('selectedItem');
}
opts.gridDataSource = new kendo.data.DataSource({
type: "json",
serverPaging: true,
serverSorting: true,
sort: sortObject,
serverFiltering: true,
allowUnsort: true,
pageSize: opts.pageSize,
group: opts.group,
transport: {
read: {
url: opts.dataSourceURL,
type: 'POST',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: function () { return opts.dataSourceParamsFunction(); }
},
parameterMap: function (options) {
return JSON.stringify(options);
}
},
schema: opts.dataSourceSchema,
});
gridExtended = $(opts.controlId).kendoGrid({
columns: opts.gridColumns,
dataSource: opts.gridDataSource,
pageable: {
refresh: true,
pageSizes: true
},
groupable: opts.groupable,
sortable: { mode: "multiple" },
filterable: false,
selectable: true,
scrollable: true,
resizable: true,
reorderable: true,
columnReorder: SetColumnsReorder,
columnResize: SetColumnsResize,
change: function () {
var gridChange = this;
gridChange.select().each(function () {
selectedItem = gridChange.dataItem($(this));
instance.data('selectedItem', selectedItem);
});
}
});
}
The code itself it's a simplified version of my plugin. I know that this may not be the best way to write a plugin as I've read the jQuery guidelines for plugin development. It would be awesome if you could point me in the right direction or tell me why my code is not working. Thanks a lot in advance!
I think you do not need that "public accessor" that you wrote, I think you actually can get it like this:
selectedItemGrid1= $("#Grid1").data('selectedItem);
selectedItemGrid2= $("#Grid2").data('selectedItem);
On a side you do not have to wrap that instance element into a jQuery object. You still be able to use rest of the jQuery methods, check the example.
I finally solved it appending a hidden input with a unique Id to the grid of the helper. On that hidden input I'm storing all the data that I want to be persistent with the Jquery .data().
So if I generate 2 grids using the plugin, each grid will have appended something like this:
<input type="hidden" id="uniqueIdHere" />

Categories