Related
I want to use selectize.js in my project. Everything works fine except one thing, when I click on a scroll-bar in drop-down menu it closes automatically and I don't understand how to fix this issue, maybe I should do something in config. Someone faced with this problem?
Here is my config object:
facility_config = {
maxItems: 1,
plugins: ['remove_button'],
valueField: 'id',
searchField: ['facility_name'],
optgroups: [
{ id: 0, group_name: 'Teams' },
{ id: 1, group_name: 'Primary Practices' },
{ id: 2, group_name: 'Facility Affiliations' }
],
optgroupField: 'group_name',
optgroupValueField: 'group_name',
optgroupLabelField: 'group_name',
lockOptgroupOrder: true,
render: {
item: function (item, escape) {
return '<div class="option">' +
'<span>' + escape(item.facility_name) + '</span>' +
'<span ng-if="item.city && item.state">' + ' ( ' + escape(item.city) + ', ' + escape(item.state) + ' )' + '</span>' +
'<span class="fa fa-asterisk text-orange"></span>'
'</div>';
},
optgroup_header: function (data, escape) {
return '<div class="optgroup-header"><strong>' + escape(data.group_name) + '</strong></div>';
},
option: function (item, escape) {
return '<div class="option">' +
'<span>' + escape(item.facility_name) + '</span>' +
'<span ng-if="item.city && item.state" class="text-muted">' + ' ( ' + escape(item.city) + ', ' + escape(item.state) + ' )' + '</span>' +
'<span class="fa fa-asterisk text-orange"></span>'
'</div>';
}
}
};
And my html:
<selectize options="model.items", config="model.facility_config", ng-model="modalObject.facility_id"></selectize>
sample data can be as :
items = [{id: 1, facility_name: 'QA', state: 'LA', city: 'San Francisco', group_name: 'Teams'}];
Requirement: To have infinite scrolling for a extjs(4.2.2) grid along with row expanding functionality.
But both the plugins together not working,
row expander plugin not allowing data to load into buffered store of a grid.
when rowexpander plugin is commented, then infinite scroll grid is loading.
how to have both the functionalities?
i have created a rowexpander plugin as below by extending extjs rowexpander,
here if i comment out below line thne atleast one rec is getting loaded
feature.getRowBodyContents = Ext.bind(me.getRowBodyContents, me);
Ext.define('Premier.view.tools.NM.Plugin.NotesGridRowExpander', {
extend: 'Ext.grid.plugin.RowExpander',
alias: 'plugin.notes-rowexpander',
rowBodyTpl: [
'<div class="notes-management-tool"> ',
'<table cellspacing="0" cellpadding="0" class="notes-management-tool-table">',
'<tr>',
'<th valign="middle" class="notes-management-tool-table-date" style="color:black;width:130px;">Last Edited Date</th>',
'<th valign="middle" class="notes-management-tool-table-note" style="color:black;width:360px;">Notes</th>',
'<th valign="middle" class="notes-management-tool-table-editedBy" style="color:black;width:210px;">Last Edited By</th>',
'<th valign="middle" class="notes-management-tool-table-actions" style="color:black;width:50px;">Actions</th>',
'</tr>',
'<tpl for=".">',
'<tr>',
'<td valign="middle" class="notes-management-tool-table-date" style="color:black">{[(Ext.util.Format.date(Ext.Date.parse(values.LastEditedDate, "MS"), "M-d-Y h:i A"))|| " "]}</td>',
'<td valign="middle"class="notes-management-tool-table-note" style="color:black">{[(values.Note)|| " "]}</td>',
'<td valign="middle" class="notes-management-tool-table-editedBy" style="color:black">{[(values.LastEditedBy)|| " "]}</td>',
'<td valign="right" class="notes-management-tool-table-actions" ><div style="margin-left:3px" data-qtip="Edit" class = "{[parent.AccountId == values.LastEditedById ? "edit-notes-record-icon-active " : "edit-notes-record-icon-inactive "]}-noteId-{[this.getStringId(values.NoteId)]}-entityId-{[this.getStringId(values.EntityId)]}-entityTypeId-{[this.getStringId(values.EntityTypeId)]}"></div><div style="margin-left:3px" data-qtip="Delete" class = "{[parent.AccountId == values.LastEditedById ? "trash-icon " : "disabled-trash-icon " ]}-noteId-{[this.getStringId(values.NoteId)]}-entityId-{[this.getStringId(values.EntityId)]}-entityTypeId-{[this.getStringId(values.EntityTypeId)]}"></div></td>',
'</tr>',
'</tpl>',
'</table>',
'</div> ',
{
getStringId: function (id) {
return id.toString();
}
}
],
expandAllFlag: false,
constructor: function () {
var me = this;
me.callParent(arguments);
},
setCmp: function (grid) {
var me = this, features, i, feature;
me.callParent(arguments);
features = grid.features;
for (i = 0; i < features.length; i++) {
if ((feature = features[i]).ftype == 'rowbody') {
break;
}
}
if (feature) {
//This function is abstracted as a private function kind of. So overriding the method to call
//our own function
feature.getRowBodyContents = Ext.bind(me.getRowBodyContents, me);
}
},
getRowBodyContents: function (record) {
var content = '', data;
if(record.data) {
data = record.data.NotesChildViews.sort(
function (rec1, rec2) {
var a= Ext.Date.parse(rec1.LastEditedDate, "MS");
var b =Ext.Date.parse(rec2.LastEditedDate, "MS");
return a>b ? -1 : a<b ? 1 : 0;
});
}
if (data) {
data.AccountId = this.grid.app.getAccountId();
content = this.rowBodyTpl.apply(data);
}
return content;
},
getHeaderConfig: function () {
var me = this;
return {
itemId: 'rowExpanderHeader',
width: 40,
lockable: false,
sortable: false,
resizable: false,
draggable: false,
hideable: false,
text: '<div class="notes-grid-expand"></div>',
menuDisabled: true,
tdCls: Ext.baseCSSPrefix + 'grid-cell-special',
innerCls: Ext.baseCSSPrefix + 'grid-cell-inner-row-expander',
renderer: function (value, metadata) {
// Only has to span 2 rows if it is not in a lockable grid.
if (!me.grid.ownerLockable) {
metadata.tdAttr += ' rowspan="2"';
}
return '<div style="margin: 4px 0px 0px 8px;" class="' + Ext.baseCSSPrefix + 'grid-row-expander" role="presentation"></div>';
},
processEvent: function (type, view, cell, rowIndex, cellIndex, e, record) {
if (type == "mousedown" && e.getTarget('.' + Ext.baseCSSPrefix + 'grid-row-expander')) {
me.toggleRow(rowIndex, record);
return me.selectRowOnExpand;
}
},
listeners: {
'afterrender': me.handleExpansion,
scope: me
}
};
},
handleExpansion: function (headerObj) {
var me = this;
headerObj.el.on('click', function () {
me.cmp.fireEvent('notes-grid-expansion');
});
},
updateHeaderText: function () {
var me = this;
if (me.expandAllFlag == false) {
me.cmp.headerCt.down('#rowExpanderHeader').setText('<div class="notes-grid-collapse"></div>');
me.expandAllFlag = true;
}
else {
me.cmp.headerCt.down('#rowExpanderHeader').setText('<div class="notes-grid-expand"></div>');
me.expandAllFlag = false;
}
},
setDefaultHeader: function () {
var me = this;
me.cmp.headerCt.down('#rowExpanderHeader').setText('<div class="notes-grid-expand"></div>');
me.expandAllFlag = false;
}
});
when getrowbodycontent is removed from setCmp then ,
when calling getrowbodycontent in setCmp,
This solution uses bufferedrenderer and rowexpander plugins. I don't know how you get data, so the example generates some fake data and loads data dynamically.
I hope this helps.
Ext.define('testmodel', {
extend: 'Ext.data.Model',
fields: [
{name: 'name', type: 'string'},
{name: 'index', type: 'number'}
]
});
Ext.define('Test.RowExpander', {
extend: 'Ext.grid.plugin.RowExpander',
rowBodyTpl: [
"<tpl>",
"<p>Item name: {name}</p>",
"<p>Item index: {index}</p>",
"</tpl>"
],
expandAllFlag: false,
constructor: function() {
this.callParent(arguments);
},
setCmp: function (grid) {
var me = this, features, i, feature;
me.callParent(arguments);
features = grid.features;
for (i = 0; i < features.length; i++) {
if ((feature = features[i]).ftype == 'rowbody') {
break;
}
}
if (feature) {
feature.getRowBodyContents = Ext.bind(me.getRowBodyContents, me);
}
},
getRowBodyContents: function (record) {
var content = '', data;
if (record.data) {
data = record.data;
}
if (data) {
content = this.rowBodyTpl.apply(data);
}
return content;
}
});
Ext.onReady(function() {
Ext.define('Test.TestWindow', {
extend: 'Ext.window.Window',
closeAction: 'destroy',
border: false,
width: 560,
height: 500,
modal: true,
closable: true,
resizable: false,
layout: 'fit',
setStoreData: function() {
var me = this;
me.storeData = [];
for (i = 1; i <= 15000; i++) {
me.storeData.push(
{"name": "Name"+i, "index": i}
);
}
},
initComponent: function() {
var me = this;
me.callParent(arguments);
me.setStoreData();
me.store = Ext.create('Ext.data.Store', {
autoLoad: false,
pageSize: 16,
data: [],
model: 'testmodel'
});
me.rowexpander = Ext.create('Test.RowExpander', {
});
me.bufferedrenderer = Ext.create('Ext.grid.plugin.BufferedRenderer', {
});
me.grid = Ext.create('Ext.grid.Panel', {
loadMask: true,
plugins: [
me.bufferedrenderer,
me.rowexpander
],
selModel: {
pruneRemoved: false
},
stripeRows: true,
store: me.store,
columnLines: false,
columns : [
{header : 'Name', sortable : true, width: 100, dataIndex : 'name'},
{header : 'Index', sortable : true, width : 100, dataIndex : 'index'}
]
});
me.add(me.grid);
me.store.loadData(me.storeData);
}
});
var win = new Test.TestWindow({
});
win.show();
});
Notes:
Tested with ExtJS 4.2.1 and Internet Explorer 11, Google Chrome 68, Mozilla Firefox 61, Microsoft Edge 42.
Fiddle can be found here.
I have the following factory I use to return a http promise with the user data from the server
(function () {
angular.module('BlurAdmin.theme')
.factory('getData', function($http){
var service = {};
service.objData = null;
service.savePromise = function(objData) {
service.objData = objData;
}
service.getSavedPromise = function() {
return service.objData;
}
service.getDataFromServer = function() {
var promise = $http.get('/admin/data');
service.savePromise(promise);
}
return service;
});
})();
I launch this http request at the run method of the app.
In another controller I have done the following
getData.getSavedPromise().then(function (data) {
$scope.newVisits = data.data.data.newVisitors;
});
var pieColor = baUtil.hexToRGB(baConfig.colors.defaultText, 0.2);
$scope.charts = [{
color: pieColor,
description: 'New Visits',
stats: '$ ' + $scope.newVisits,
icon: 'person',
}, {
color: pieColor,
description: 'Purchases',
stats: '$ 89,745',
icon: 'money',
}, {
color: pieColor,
description: 'Active Users',
stats: '178,391',
icon: 'face',
}, {
color: pieColor,
description: 'Returned',
stats: '32,592',
icon: 'refresh',
}
];
The Data structure is a little messed up and I need to fix it but that is beside the point.
I use for example
<div class="description-stats">{{ ::chart.stats }}</div>
In the html.
The issue is that the data is not being bind and I see undefined in the page.
What am I doing wrong?
I'm very new to ExtJS and I'm having a hard time determining the proper MVC architecture to display custom XTemplates using an non-hard coded store.
In the example code below I have 1, 2, and 3 working. However, 4 is not working. I'm pretty sure it's because there is a timing issue. Stores 1 - 3 are hard coded whereas 4 is created on the "load" event.
What is the best way to configure a custom template with an ajax store so that the store is completely loaded before rendering the custom html?
Ext.define('myApp.view.task.Custom', {
extend: 'Ext.panel.Panel',
alias: 'widget.task.custom',
title: 'Custom List',
initComponent: function () {
var me = this;
var data = {name: "One", age: "1"};
// Template Test (#1)
var tpl = new Ext.XTemplate(
'<h2>1) Simple Template</h2>',
'<tpl for=".">',
'<p>{name}, {age}</p>',
'</tpl>'
);
var generatedHtml1 = tpl.apply(data);
// Template Test Store (hard coded)
var myStore = Ext.create('Ext.data.Store', {
fields: ["name", "age"],
data: [
{name: "One", age: "1"},
{name: "Two", age: "2"},
{name: "Three", age: "3"},
{name: "Four", age: "4"},
{name: "Five", age: "5"}
]
});
// UL List Template (#2)
var tpl2 = new Ext.XTemplate(
'<h2>2) UL List Template</h2>',
'<ul>',
'<tpl for=".">',
'<li>Name: <b>{data.name}</b>, Age: <b>{data.age}</b></li>',
'</tpl>',
'</ul>'
);
var generatedHtml2 = tpl2.apply(myStore);
// Table Template (#3)
var tpl3 = new Ext.XTemplate(
'<h2>3) Table Template</h2>',
'<table>',
'<tr><th>Name</th><th>Age</th></tr>',
'<tpl for=".">',
'<tr><td>{data.name}</td><td>{data.age}</td></tr>',
'</tpl>',
'</table>'
);
var generatedHtml3 = tpl3.apply(myStore);
var me = this;
Ext.applyIf(me, {
items: [
{
style: 'margin: 25px',
html: generatedHtml1 // #1 Works fine
},
{
style: 'margin: 25px',
html: generatedHtml2 // #2 Works fine
},
{
style: 'margin: 25px',
html: generatedHtml3 // #3 Works fine
},
{
style: 'margin: 25px',
html: this.generateDynamicHtml() // #4 Does not work
}
]
});
me.callParent(arguments);
},
generateDynamicHtml: function () {
var title = '<h2>4) Trying to generate a simple table from a store</h2>';
var generatedTaskTable;
var taskStore = Ext.create('myApp.store.Tasks');
taskStore.load();
taskStore.on("load", function () {
var taskTpl = new Ext.XTemplate(
'<h2>Task Table Template</h2>',
'<table>',
'<tr><th>Name</th>',
'<th>Id</th></tr>',
'<tpl for=".">',
'<tr>',
'<td>{data.name}</td>',
'<td>{data.id}</td>',
'</tr>',
'</tpl>',
'</table>'
);
generatedTaskTable = taskTpl.apply(taskStore);
});
return title + generatedTaskTable;
}
});
I'm getting Cannot call method 'getTime' of undefined error when I try to create a new event by clicking on Ext JS 4 calendar.
Here's my event store defition:
Ext.calendar.data.EventMappings = {
// These are the same fields as defined in the standard EventRecord object but the
// names and mappings have all been customized. Note that the name of each field
// definition object (e.g., 'EventId') should NOT be changed for the default fields
// as it is the key used to access the field data programmatically.
EventId: {name: 'id', mapping:'id', type:'int'}, // int by default
CalendarId: {name: 'cid', mapping: 'cid', type: 'int'}, // int by default
Title: {name: 'title', mapping: 'title'},
StartDate: {name: 'start', mapping: 'start', type: 'date', dateFormat: 'c'},
EndDate: {name: 'end', mapping: 'end', type: 'date', dateFormat: 'c'},
RRule: {name: 'recur_rule', mapping: 'recur_rule'},
Location: {name: 'loc', mapping: 'loc'},
Notes: {name: 'notes', mapping: 'notes'},
Url: {name: 'url', mapping: 'url', type : 'int' },
IsAllDay: {name: 'ad', mapping: 'ad', type: 'boolean'},
Reminder: {name: 'rem', mapping: 'rem'},
// We can also add some new fields that do not exist in the standard EventRecord:
CreatedBy: {name: 'collabUserId', mapping: 'collabUserId', type: 'int'}
};
// Don't forget to reconfigure!
Ext.calendar.data.EventModel.reconfigure();
Ext.define(appName + '.store.Events', {
extend : 'Ext.calendar.data.MemoryEventStore',
// model : appName + '.model.Event',
autoLoad : false,
autoSync : true,
proxy : {
type : 'ajax',
// url : 'randevu/loadEvents.ajax',
api : {
read : 'randevu/loadEvents.ajax',
create : 'randevu/saveOrUpdateEvent.ajax',
update : 'randevu/saveOrUpdateEvent.ajax',
destroy : 'randevu/deleteEvent.ajax'
},
reader : {
type : 'json',
root : 'data',
successProperty : 'success',
totalProperty : 'totalCount',
idProperty : 'id'
},
writer : {
type : 'json',
writeAllFields : true,
encode : true,
root : 'data'
}
}
});
And my Calendar view:
Ext.define(appName + '.view.randevu.RandevuPanel', {
extend : appName + '.view.base.BasePanel',
requires : [ 'Ext.calendar.util.Date',
'Ext.calendar.CalendarPanel',
'Ext.calendar.data.MemoryCalendarStore',
'Ext.calendar.data.MemoryEventStore',
'Ext.calendar.data.Events',
'Ext.calendar.data.Calendars',
'Ext.calendar.form.EventWindow',
appName + '.view.user.UserCombo'
],
alias : 'widget.randevupanel',
iconCls : 'icon-calendar',
width : '100%',
// titleAlign : 'center',
layout : {
type : 'hbox',
align : 'stretch'
},
defaults : { flex : 1 }, //auto stretch
initComponent: function() {
var me = this;
this.calendarStore = OnlineRandevuSistemi.app.getStore('Calendars');
this.eventStore = OnlineRandevuSistemi.app.getStore('Events');
this.updateTitle = function(startDt, endDt) {
var p = Ext.getCmp('app-center'),
fmt = Ext.Date.format;
if(Ext.Date.clearTime(startDt).getTime() == Ext.Date.clearTime(endDt).getTime()){
p.setTitle(fmt(startDt, 'F j, Y'));
}
else if(startDt.getFullYear() == endDt.getFullYear()){
if(startDt.getMonth() == endDt.getMonth()){
p.setTitle(fmt(startDt, 'F j') + ' - ' + fmt(endDt, 'j, Y'));
}
else{
p.setTitle(fmt(startDt, 'F j') + ' - ' + fmt(endDt, 'F j, Y'));
}
}
else{
p.setTitle(fmt(startDt, 'F j, Y') + ' - ' + fmt(endDt, 'F j, Y'));
}
};
this.showEditWindow = function(rec, animateTarget){
console.log(rec);
if(!this.editWin){
this.editWin = Ext.create('Ext.calendar.form.EventWindow', {
calendarStore: this.calendarStore,
listeners: {
'eventadd': {
fn: function(win, rec){
win.hide();
rec.data.IsNew = false;
this.eventStore.add(rec);
// this.eventStore.sync();
this.showMsg('<b>'+ rec.data.Title +'</b> etkinliği eklendi.');
},
scope: this
},
'eventupdate': {
fn: function(win, rec){
win.hide();
rec.commit();
// this.eventStore.sync();
this.showMsg('<b>'+ rec.data.Title + '</b> etkinliği düzenlendi.');
},
scope: this
},
'eventdelete': {
fn: function(win, rec){
this.eventStore.remove(rec);
// this.eventStore.sync();
win.hide();
this.showMsg('<b>'+ rec.data.Title +'</b> etkinliği silindi.');
},
scope: this
},
'editdetails': {
fn: function(win, rec){
win.hide();
Ext.getCmp('app-calendar').showEditForm(rec);
}
}
}
});
}
this.editWin.show(rec, animateTarget);
};
this.showMsg = function(msg){
Ext.example.msg('Bilgilendirme', msg);
// Ext.fly('app-msg').update(msg).removeCls('x-hidden');
};
this.clearMsg = function(){
Ext.fly('app-msg').update('').addCls('x-hidden');
};
this.title = bundle.getMsg('randevupanel.title');
this.items = [{
id: 'app-center',
title: '...', // will be updated to the current view's date range
titleAlign : 'center',
region: 'center',
layout: 'border',
listeners: {
'afterrender': function(){
Ext.getCmp('app-center').header.addCls('app-center-header');
}
},
items: [{
xtype: 'container',
id:'app-west',
region: 'west',
width: Ext.themeName === 'neptune' ? 214 : 179,
items: [{
xtype: 'datepicker',
id: 'app-nav-picker',
cls: 'ext-cal-nav-picker',
listeners: {
'select': {
fn: function(dp, dt){
Ext.getCmp('app-calendar').setStartDate(dt);
},
scope: this
}
}
}]
},{
xtype: 'calendarpanel',
eventStore: this.eventStore,
// eventStore: 'Events',
calendarStore: this.calendarStore,
border: false,
id:'app-calendar',
region: 'center',
activeItem: 3, // month view
monthViewCfg: {
showHeader: true,
showWeekLinks: true,
showWeekNumbers: true
},
listeners: {
'eventclick': {
fn: function(vw, rec, el){
this.showEditWindow(rec, el);
this.clearMsg();
},
scope: this
},
'eventover': function(vw, rec, el){
//console.log('Entered evt rec='+rec.data.Title+', view='+ vw.id +', el='+el.id);
},
'eventout': function(vw, rec, el){
//console.log('Leaving evt rec='+rec.data.Title+', view='+ vw.id +', el='+el.id);
},
'eventadd': {
fn: function(cp, rec){
this.showMsg('Event '+ rec.data.Title +' was added');
},
scope: this
},
'eventupdate': {
fn: function(cp, rec){
this.showMsg('Event '+ rec.data.Title +' was updated');
},
scope: this
},
'eventcancel': {
fn: function(cp, rec){
// edit canceled
},
scope: this
},
'viewchange': {
fn: function(p, vw, dateInfo){
if(this.editWin){
this.editWin.hide();
}
if(dateInfo){
// will be null when switching to the event edit form so ignore
Ext.getCmp('app-nav-picker').setValue(dateInfo.activeDate);
this.updateTitle(dateInfo.viewStart, dateInfo.viewEnd);
}
},
scope: this
},
'dayclick': {
fn: function(vw, dt, ad, el){
this.showEditWindow({
StartDate: dt,
IsAllDay: ad
}, el);
this.clearMsg();
},
scope: this
},
'rangeselect': {
fn: function(win, dates, onComplete){
this.showEditWindow(dates);
this.editWin.on('hide', onComplete, this, {single:true});
this.clearMsg();
},
scope: this
},
'eventmove': {
fn: function(vw, rec){
var mappings = Ext.calendar.data.EventMappings,
time = rec.data[mappings.IsAllDay.name] ? '' : ' \\a\\t g:i a';
rec.commit();
this.showMsg('Event '+ rec.data[mappings.Title.name] +' was moved to '+
Ext.Date.format(rec.data[mappings.StartDate.name], ('F jS'+time)));
this.eventStore.sync();
},
scope: this
},
'eventresize': {
fn: function(vw, rec){
rec.commit();
this.showMsg('Event '+ rec.data.Title +' was updated');
},
scope: this
},
'eventdelete': {
fn: function(win, rec){
this.eventStore.remove(rec);
this.showMsg('Event '+ rec.data.Title +' was deleted');
},
scope: this
},
'initdrag': {
fn: function(vw){
if(this.editWin && this.editWin.isVisible()){
this.editWin.hide();
}
},
scope: this
}
}
}]
}];
this.scdUserLabel = Ext.create('Ext.form.DisplayField', {
hideLabel : true,
value : 'Misafir Oturumu'
});
this.btnLogin = Ext.create('Ext.Button', {
text : bundle.getMsg('randevupanel.btnLogin.text'),
iconCls : 'icon-sign-in',
action : 'login',
tooltip : bundle.getMsg('randevupanel.btnLogin.tip')
});
this.btnLogout = Ext.create('Ext.Button', {
text : bundle.getMsg('randevupanel.btnLogout.text'),
iconCls : 'icon-sign-out',
action : 'logout',
hidden : true,
tooltip : bundle.getMsg('randevupanel.btnLogout.tip')
});
this.tbar = Ext.create('Ext.Toolbar', {
items : [ ' ', me.scdUserLabel, '->', me.btnLogin, me.btnLogout ]
});
this.callParent(arguments);
}
});