I'm using JTable and JQuery for an html page, adding the records manually in JTable using jtable addRecord option. I want to delete the added record based on user selection locally i.e., on client side only. Hence, I use the below code, the record contains TeamName & TeamDescription.
$.fn.deleteTeamRow = function() {
var $selectedRows = $('#TeamContainer').jtable('selectedRows');
$selectedRows.each(function () {
var record = $(this).data('record');
var teamname = record.TeamName;
$('#TeamContainer').jtable('deleteRecord', {
key: teamname,
clientOnly: true,
success: (function() {
alert("record deleted");
}),
error: (function() {
alert("record deletion error!");
})
});
});
};
Unable to either get the success or error alert.
Kindly, let me know how to delete a record on client side only.
I was able to resolve the issue the 'key' was missed while defining the columns in the Table.
$('#TeamContainer').jtable({
selecting: true,
columnResizable: false,
selecting: true, //Enable selecting
multiselect: true, //Allow multiple selecting
selectingCheckboxes: true,
actions: {
},
fields: {
TeamName: {
title: 'Team Name',
**key: true,**
sorting: true
},
TeamDescription: {
title: 'Team Description',
create: false
}
}
});
Related
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);
}
}
}
Need to bind my form elements separately for different buttons. Using allowBlank in elements for sending binding conditions and formBind in buttons for binding the buttons. Need to do this like in this simplest way. (ExtJs 4.2.1 Classic)
Example
Ext.create('Ext.form.Panel', {
......
items: [
Ext.create('Ext.form.field.Date', {
.....,
allowBlank: false, //bind for both search & download button.
.....
}),
......, //// All rest elements bind for both search & download button.
Ext.create('Ext.form.ComboBox', {
......,
allowBlank: false, //bind for only download button.
......
})
],
buttons: [
{
text: 'Search',
formBind: true, /// Need to bind for specific field only.
},
{
text: 'Download',
formBind: true, /// Need to bind for all.
},
............
});
If any other data or details is necessary then please don't hesitate to ask.
I created a fiddle here that I think should accomplish what you're trying to do. The idea to use an event listener on the combobox, instead of the formBind config of the Download button:
https://fiddle.sencha.com/#view/editor&fiddle/289a
Ext.create('Ext.form.Panel', {
renderTo: Ext.getBody(),
itemId: 'exampleForm',
items: [Ext.create('Ext.form.field.Date', {
allowBlank: false, //bind for both search & download button.
}),
Ext.create('Ext.form.ComboBox', {
allowBlank: false, //bind for only download button.
listeners: {
change: function (thisCombo, newValue, oldValue, eOpts) {
if (Ext.isEmpty(newValue)) {
thisCombo.up('#exampleForm').down('#btnDownload').setDisabled(true);
} else {
thisCombo.up('#exampleForm').down('#btnDownload').setDisabled(false);
}
}
},
store: ['item1', 'item2']
})
],
buttons: [{
text: 'Search',
formBind: true, /// Need to bind for specific field only.
}, {
itemId: 'btnDownload',
text: 'Download',
disabled: true
//formBind: true, /// Need to bind for all.
}]
});
There is no standard quick way to do this, you might want to write a plugin for this. I've put together one:
Ext.define('App.plugin.MultiDisableBind', {
extend: 'Ext.AbstractPlugin',
alias: 'plugin.multidisablebind',
/**
* #cfg
* Reference to the fields that this button depends on.
* Can contain either direct references, or a query selectors that will be
* executed with the button as the root
*/
depFields: null,
/**
* #property
* A map object with field ids as key, and field values as value
*/
valuesMap: null,
init: function (cmp) {
this.setCmp(cmp);
cmp.on('render', this.setup, this);
},
setup: function () {
var cmp = this.getCmp(),
depFields = this.depFields,
valuesMap = {};
if (!Ext.isArray(depFields)) {
depFields = [depFields];
}
Ext.Array.forEach(depFields, function (field) {
if (Ext.isString(field)) {
field = cmp.query(field)[0];
}
cmp.mon(
field,
'change',
Ext.Function.createThrottled(this.updateValuesMap, 300, this),
this
);
valuesMap[field.getId()] = field.getValue();
}, this);
this.valuesMap = valuesMap;
this.updateCmpDisabled();
},
updateValuesMap: function (depField, newValue) {
this.valuesMap[depField.getId()] = newValue;
this.updateCmpDisabled();
},
updateCmpDisabled: function () {
var cmp = this.getCmp(),
toDisable = true;
Ext.Object.each(this.valuesMap, function (fieldId, fieldValue) {
if (!Ext.isEmpty(fieldValue)) {
toDisable = false;
return false
}
});
cmp.setDisabled(toDisable);
}
});
You can use this plugin in your buttons like so:
xtype: 'button',
text: 'My button',
plugins: {
ptype: 'multidisablebind',
depFields: ['^form #fieldQuery', fieldVar]
}
In the depFields config you specify references to the fields that button's disabled state depends on, and the plugin will monitor these fields, so that on each field value change it will update the disabled state.
Here is a working fiddle: https://fiddle.sencha.com/#view/editor&fiddle/28cm
I have created a fiddle for you. The code uses bind and formBind respectively for the two different buttons. May be you want something like this.
I need to employ a filter function to implement a heuristic for selecting records. Simple field/value checks, alone, are inadequate for our purpose.
I'm trying to follow the examples for function filters, but for some reason, the "allowFunctions" flag keeps getting set to false.
I attempt to set the allowFunctions property to true in the storeConfig:
storeConfig: {
models: ['userstory', 'defect'],
allowFunctions: true,
filters: [{
// This did not work ...
property: 'Iteration.Name',
value: 'Sprint 3',
// Trying dynamic Filter Function. Update: Never called.
filterFn: function (item) {
console.log("Entered Filter Function!");
var iter = item.get("Iteration");
console.log("Iteration field: ", iter);
if (iter !== null && iter !== undefined) {
return (iter.name === "Sprint 3");
} else {
return false;
}
}
}]
},
After the grid view renders, I inspect it the store configuration and its filters:
listeners: {
afterrender: {
fn: function (_myVar, eOpts) {
console.log("Arg to afterrender: ", _myVar, " and ", eOpts);
var _myStore = _myVar.getStore();
console.log("Store filters: ", _myStore.filters);
}
}
},
What I find is that the allowFunctions property has been set back to false and I see that the filter function I specified never fired.
Console Screen Shot
So either I am setting allowFunctions to true in the wrong place, or something built into the Rally Grid View and its data store prohibits filter functions and flips the flag back to false.
OR there's a third option betraying how badly off my theory of operation is.
Oh, wise veterans, please advise.
Here's the entire Apps.js file:
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function () {
//Write app code here
console.log("Overall App Launch function entered");
//API Docs: https://help.rallydev.com/apps/2.1/doc/
}
});
Rally.onReady(function () {
Ext.define('BOA.AdoptedWork.MultiArtifactGrid', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function () {
console.log("onReady Launch function entered");
this.theGrid = {
xtype: 'rallygrid',
showPagingToolbar: true,
showRowActionsColumn: false,
editable: false,
columnCfgs: [
'FormattedID',
'Name',
'ScheduleState',
'Iteration',
'Release',
'PlanEstimate',
'TaskEstimateTotal',
'TaskActualTotal', // For some reason this does not display ?? :o( ??
'TaskRemainingTotal'
],
listeners: {
afterrender: {
fn: function (_myVar, eOpts) {
console.log("Arg to afterrender: ", _myVar, " and ", eOpts);
var _myStore = _myVar.getStore();
console.log("Store filters: ", _myStore.filters);
}
}
},
storeConfig: {
models: ['userstory', 'defect'],
allowFunctions: true,
filters: [{
// This did not work ...
property: 'Iteration.Name',
value: 'Sprint 3',
// Trying dynamic Filter Function. Update: Never called.
filterFn: function (item) {
console.log("Entered Filter Function!");
var iter = item.get("Iteration");
console.log("Iteration field: ", iter);
if (iter !== null && iter !== undefined) {
return (iter.name === "Sprint 3");
} else {
return false;
}
}
}]
},
context: this.getContext(),
scope: this
};
this.add(this.theGrid);
console.log("The Grid Object: ", this.theGrid);
}
});
Rally.launchApp('BOA.AdoptedWork.MultiArtifactGrid', {
name: 'Multi-type Grid'
});
});
This is a tricky one since you still want your server filter to apply and then you want to further filter the data down on the client side.
Check out this example here:
https://github.com/RallyCommunity/CustomChart/blob/master/Settings.js#L98
I think you can basically add a load listener to your store and then within that handler you can do a filterBy to further filter your results on the client side.
listeners: {
load: function(store) {
store.filterBy(function(record) {
//return true to include record in store data
});
}
}
I'm not familiar with allowFunctions, but in general remoteFilter: true/false is what controls whether the filtering is occurring server side or client side. remoteFilter: true + the load handler above gives you the best of both worlds.
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
I'm using a jquery script called jTable (www.jtable.org) to implement dynamic tables in my web application. In order to include a table on a particular page, you must include the following code to declare its properties:
<script type="text/javascript">
$(document).ready(function () {
$('#MyTableContainer').jtable({
//General options comes here
actions: {
//Action definitions comes here
},
fields: {
//Field definitions comes here
}
});
});
</script>
An example of what might go into the fields property:
fields: {
StudentId: {
key: true,
create: false,
edit: false,
list: false
},
Name: {
title: 'Name',
width: '23%'
},
EmailAddress: {
title: 'Email address',
list: false
},
Password: {
title: 'User Password',
type: 'password',
list: false
},
Gender: {
title: 'Gender',
width: '13%',
options: { 'M': 'Male', 'F': 'Female' }
},
BirthDate: {
title: 'Birth date',
width: '15%',
type: 'date',
displayFormat: 'yy-mm-dd'
}
}
The problem is I use the same table (or very similar tables) throughout my web application. I would like to be able to implement a way to store the fields in an external .js file and then refer to it on each page, thus avoiding copying and pasting. On some pages, I may only include some of the above fields (ex. I may want to exclude Password and EmailAddress) or make slight variations to the fields when I load them (ie. use a different displayFormat (for BirthDate) than the default in the external .js file on a particular page.
Thanks!
You can do this in several ways. Here's a simple one:
main.js
//should be modularized/namespaced
var defaultStudentTableFieldsCfg = {
...
};
other-file.js
$(function () {
var tableFieldsCfg = $.extend({}, defaultStudentTableFieldsCfg);
//define new column
tableFieldsCfg.someNewCol = {
//...
};
//remove some column
delete tableFieldsCfg.Password;
//override config
tableFieldsCfg.Gender.title = 'GENDER';
//it would be better not to hard-code #MyTableContainer here
$('#MyTableContainer').jtable({ fields: tableFieldsCfg });
});
You could create functions that you put in external JS files. Then those functions could return the JSON objects needed to construct your jTable.
The problem is the fact that you have a JSON object and that can not be just referenced in a JavaScript file. If you want to load the file, you would need to use something like getJSON and than use that with jQuery.
function createTable(fields) {
$('#MyTableContainer').jtable({
//General options comes here
actions: {
//Action definitions comes here
},
fields: fields
});
}
$(function(){
$.getJSON("YourFields.json", createTable);
});
Now what you are trying to do is reference a global variable.
Place the file before and reference the global variable.
<script type="text/javascript" src="YourFields.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#MyTableContainer').jtable({
actions: {
},
fields: fields
});
});
</script>
The YourFields.js file should look more like
if (!window.appDefaults) {
window.appDefaults = {}
}
window.appDefaults.fields = {
StudentId: {
key: true,
...
};