ExtJs 4.2 Extend Custom Model using MVC problems - extjs

Using ExtJs 4.2 with MVC pattern
I am trying to make a custom model, store, proxy, reader, writer but am having problems getting it to work in the MVC pattern. I followed this example to extend a model and I can see it working only if it is not used in the MVC way.
My store refers to a model such as Contacts defined in the model property, then Contacts refers to custom model WakandaModel using the model property. But when I create my store which refers to Contacts none of the model properties or proxy defined in the custom WakandaModel is brought over to the stores model.
Here is my code, I have left comments in so you can see what I have attempted to try. Thanks for any help!
App Code
Ext.Loader.setConfig({
enabled : true,
paths : {
'Ext.ux' : "lib/extux",
'Wakanda' : "lib/extux/wakanda"
}
});
Ext.application({
name : 'SimplyFundraising',
autoCreateViewport : true,
requires : ['Ext.ux.Router', // Require the UX
'Ext.window.MessageBox'],
controllers : ['Contacts'],
});
Custom Model
Ext.define('Wakanda.Model', {
extend: 'Ext.data.Model',
idProperty: '__KEY',
stampProperty: '__STAMP',
defaultProxyType: 'wakanda',
onClassExtended: function(cls, data) {
// debugger;
// cls.apply(this)
// var parts = data.$className.split('.');
// var entity = parts[2]
// var catalog = this.prototype.getCatalog(entity),
// attributes = catalog.attributes;
// for (var i = 0, l = attributes.length; i < l; i++) {
// if (attributes[i].name === 'ID') {
// attributes[i].persist = false;
// }
// }
// attributes.push({name: this.prototype.idProperty});
// attributes.push({name: this.prototype.stampProperty});
// // data.fields = attributes;
// // debugger;
// //this.setFields(data.fields)
// // var mymodel = Ext.ModelManager.getModel(data.$className);
// debugger;
// Ext.appy(this);
// //this.superclass.superclass.$onExtended.apply(this, arguments);
},
getCatalog: function(className) {
var catalog;
Ext.Ajax.request({
async: false,
url: 'http://127.0.0.1:8081/cors/$catalog/' + className,
success: function(response) {
catalog = Ext.decode(response.responseText);
}
});
return catalog;
}
});
Custom proxy
Ext.define('Wakanda.Proxy', {
extend: 'Ext.data.proxy.Rest',
// alternateClassName: 'SimplyFundraising.data.WakandaProxy',
alias : 'proxy.wakanda',
sortParam: '$orderby',
filterParam: '$filter',
startParam: '$skip',
limitParam: '$top',
// groupersParam: '$group',
reader: 'wakanda',
writer: 'wakanda',
actionMethods: {
create : 'POST',
read : 'GET',
update : 'POST',
destroy: 'POST'
},
buildUrl: function(request) {
debugger;
var modelName = this.model.modelName,
operation = request.operation,
records = operation.records || [],
record = records[0],
id = record ? record.getId() : operation.id,
url = '/cors/' + modelName,
action = request.action;
if (this.appendId && id && (action === 'read' || action === 'destroy')) {
url += '(' + id + ')';
}
request.url = url;
// console.log("buildUrl", this, arguments, request.url);
if (action !== 'read') {
if (action === 'create') action = 'update';
else if (action === 'destroy') action = 'delete';
url = Ext.urlAppend(url, '$method=' + action);
}
if (this.noCache) {
url = Ext.urlAppend(url, Ext.String.format("{0}={1}", this.cacheString, Ext.Date.now()));
}
return url;
},
encodeSorters: function(sorters) {
var min = [],
length = sorters.length,
i = 0, sort = '';
for (; i < length; i++) {
sort += sorters[i].property + ' ' + sorters[i].direction + ' ';
}
return sort;
},
encodeFilters: function(filters) {
var min = [],
length = filters.length,
i = 0, filter = '';
for (; i < length; i++) {
filter += filters[i].property + ' eq ' + filters[i].value + '# ';
}
return filter;
}
});
Custom reader
Ext.define('Wakanda.reader', {
extend: 'Ext.data.reader.Json',
//alternateClassName: 'SimplyFundraising.data.WakandaReader',
alias : 'reader.wakanda',
root: '__ENTITIES',
totalProperty: '__COUNT',
getData: function(data) {
if (Ext.isObject(data) && !data[this.root]) {
data = [data];
}
return data;
}
});
Custom writer
Ext.define('Wakanda.writer', {
extend: 'Ext.data.writer.Json',
// alternateClassName: 'SimplyFundraising.data.WakandaWriter',
alias: 'writer.wakanda',
writeAllFields: false,
getRecordData: function(record) {
var isPhantom = record.phantom === true,
writeAll = this.writeAllFields || isPhantom,
nameProperty = this.nameProperty,
fields = record.fields,
data = {},
changes,
name,
field,
key;
if (writeAll) {
// console.log("getRecordData1", this, arguments);
fields.each(function(field){
if (field.persist) {
name = field[nameProperty] || field.name;
data[name] = record.get(field.name);
} else {
}
});
} else {
changes = record.getChanges();
// console.log("getRecordData2", this, arguments, changes);
for (key in changes) {
if (changes.hasOwnProperty(key)) {
field = fields.get(key);
name = field[nameProperty] || field.name;
data[name] = changes[key];
}
}
if (!isPhantom) {
data[record.idProperty] = record.getId();
data[record.stampProperty] = record.get(record.stampProperty);
}
}
return {'__ENTITIES': [data]};
}
});
Contacts Model
Ext.define('SimplyFundraising.model.Contact', {
extend : 'Wakanda.Model' ,
//constructor: function() {
//alert(“Going to call parent’s overriden constructor…”);
// this.callParent(arguments);
// return this;
// }
});
Contacts Store
Ext.define('SimplyFundraising.store.Contacts', {
extend : 'Ext.data.Store',
model : 'SimplyFundraising.model.Contact',
autoLoad : true,
autoSync : true,
// constructor: function() {
// this.model = Ext.create('SimplyFundraising.model.Contact')
//alert(“Going to call parent’s overriden constructor…”);
// this.callParent(arguments);
return this;
// }
});
Contacts Controller
Ext.define('SimplyFundraising.controller.Contacts', {
extend : 'Ext.app.Controller',
models : ['Contact'],
views : ['contacts.List', 'contacts.Edit'],
init : function() {
this.control({
'contactslist' : {
itemdblclick : this.editContact,
removeitem : this.removeContact
},
'contactslist > toolbar > button[action=create]' : {
click : this.onCreateContact
},
// 'contactsadd button[action=save]': {
// click: this.doCreateContact
// },
'contactsedit button[action=save]' : {
click : this.updateContact
}
});
},
list : function() {
// var mystore = Ext.StoreMgr.lookup('Contacts');
// var myContact = this.getModel('Contact')
// var User = this.getModel('User');
//debugger;
// var mystore = Ext.create('SimplyFundraising.store.Contacts')
// var myContact = this.getModel('Contact').create()
// var bb = myContact.create()
// var rr = Ext.create('SimplyFundraising.model.Contact')
var mystore = Ext.create('SimplyFundraising.store.Contacts')
debugger;
// mystore.proxy.api.read = users.proxy.api.read + '(17)'
//mystore.proxy.extraParams = { $expand: 'ContactType'};
mystore.load();
//var test = Ext.ModelManager.getModel('Contact');
// //var User = this.getContactModel();
// User.load(258, {
// success: function(user) {
// console.log("Loaded user 258: " + user.get('lastName'));
// }
// });
},
editContact : function(grid, record) {
var view = Ext.widget('contactsedit');
view.down('form').loadRecord(record);
this.addnew = false
},
removeContact : function(Contact) {
Ext.Msg.confirm('Remove Contact ' + Contact.data.lastName, 'Are you sure?', function(button) {
if (button == 'yes') {
this.getContactsStore().remove(Contact);
}
}, this);
},
onCreateContact : function() {
var view = Ext.widget('contactsedit');
this.addnew = true
},
// doCreateContact: function (button) {
// var win = button.up('window'),
// form = win.down('form'),
// values = form.getValues(),
// store = this.getContactsStore();
// if (form.getForm().isValid()) {
// store.add(values);
// win.close();
// }
// },
updateContact : function(button) {
var win = button.up('window'), form = win.down('form'), record = form.getRecord(), values = form.getValues(), store = this.getContactsStore();
if (form.getForm().isValid()) {
if (this.addnew == true) {
store.add(values);
} else {
record.set(values);
}
win.close();
}
}
});

I got this working now:
It looks like my custom wakanda model,proxy,reader,writer where not loading. Still a bit confused on how MVC references classes and loads files and instantiates classes, which I asked in other question.
Any way the fix was to add a requires to the custom wakanda model and proxy
For the Wakanda model add requires: ['Wakanda.proxy'],
For Wakanda proxy add requires: ['Wakanda.reader', 'Wakanda.writer'],
now the inheritance is working as expected.

Related

How can I link data coming from an API to a column in a data table in Angularjs

There is a data table which is getting data from an API.
This API is responsible for populating every column on the data table. I added a new column named "Project Involved" which should get filled by the data "ProjectNames" coming from API.
The problem that am facing is- I am not able to link this data to the column on data table.
There are other columns that are getting populated.
This is the column name:
{
data: 'ProjectsInvolved',
title: $translate.instant('Projects involved'),
width: 80
}
This is where we link the API to the data table:
"use strict";
angular
.module('project')
.controller(
'ProjectPermissionsGridController',
function (
$scope,
roleConstants,
$timeout,
FormHelperService,
$translate,
$mdDialog,
logger,
projectConstants,
DateHelperService,
ResourceService,
ProjectService,
$stateParams,
$filter
) {
var pm = this;
pm.resources = [];
pm.copyOfAllResources = [];
pm.pmFormBtn = $translate.instant('btn.save');
pm.projectMemberList = [];
pm.IsProjectManager = false;
pm.maxAllowedHoursLimit = projectConstants.PROJECT_COST_PER_HOUR;
pm.projectMembersData = {
EmpID: '',
Read: roleConstants.NONE,
Write: roleConstants.NONE,
IsProjectManager: false,
// ProjectNames: pm.projectMemberList.ProjectNames
ProjectNames: ''
};
pm.showNoErrorsPerm = true;
pm.maxDate = DateHelperService.setTimeFormattedObject(new Date());
var currentIndex = '';
pm.isProjectMemberEdit = false;
var oldProjectMemberData = {};
pm.udpateResourcePersmissions = function () {
if (pm.projectMembersData.IsProjectManager) {
pm.projectMembersData.Read = roleConstants.ALL;
pm.projectMembersData.Write = roleConstants.ALL;
}
};
pm.initDataTableConfig = function (column, config, api) {
$scope.dtColumns = column;
$scope.dtConfig = config;
$scope.dtApiProjectMembers = api;
};
// Catching the event and binding the data
$scope.$on('evt.project-member-details', function (e, projectMembers) {
pm.projectMemberList = projectMembers;
pm.bindDataToGrid(false, projectMembers);
});
$scope.$on('evt.resources-list', function (e, resources) {
pm.resources = resources;
pm.copyOfAllResources = resources;
});
// On change to remove the cost per hour required validation.
pm.removeCostperHourValidation = function () {
if (!pm.projectMembersData.CostPerHour) {
pm.projectMembersData.CostPerHour = null;
}
if (
parseFloat(pm.projectMembersData.CostPerHour) >
pm.maxAllowedHoursLimit
) {
pm.projectMembersData.CostPerHour = pm.maxAllowedHoursLimit;
}
};
/**
* Add / update new data to project members grid.
*/
pm.addNewProjectMember = function (valid, $event) {
if (!valid) {
$scope.showNoErrorsPerm = false;
return false;
}
pm.projectMembersData.ProjectMember =
FormHelperService.getSelectedObject(
pm.resources,
'EmpID',
pm.projectMembersData.EmpID,
false
).EmpFirstName +
' ' +
FormHelperService.getSelectedObject(
pm.resources,
'EmpID',
pm.projectMembersData.EmpID,
false
).EmpLastName;
pm.projectMembersData.ReadText = projectConstants.PERMISSION_TYPE_OBJ[
pm.projectMembersData.Read
]
? projectConstants.PERMISSION_TYPE_OBJ[pm.projectMembersData.Read]
: '--';
pm.projectMembersData.WriteText = projectConstants.PERMISSION_TYPE_OBJ[
pm.projectMembersData.Write
]
? projectConstants.PERMISSION_TYPE_OBJ[pm.projectMembersData.Write]
: '--';
// pm.projectMembersData.ProjectsInvolved = 'OSMOSYS';
if ($scope.isProjectEdit) {
membersEditProjectForm();
} else {
memberNewProjectForm($event);
}
};
/**
* Function to be executed in the new project page.
* #param {*} event
*/
function memberNewProjectForm($event) {
// Setting this value at the time of clicking on edit button.
if (pm.isProjectMemberEdit) {
oldProjectMemberData = {};
angular.extend(
pm.projectMemberList[currentIndex],
pm.projectMembersData
);
pm.pmFormBtn = $translate.instant('btn.add');
} else {
pm.projectMembersData.CreatedOn =
DateHelperService.setTimeFormatString(new Date());
pm.projectMemberList.splice(0, 0, pm.projectMembersData);
// remove that element from employees dropdown to not to select it again
enableOrDisableEmployee(pm.projectMembersData.EmpID, true);
}
angular.element($event.target).data('isInvalid', true);
$scope.showNoErrorsPerm = true;
pm.projectMembersData = {
EmpID: '',
Read: roleConstants.NONE,
Write: roleConstants.NONE,
IsProjectManager: false,
ProjectNames: ''
};
pm.bindDataToGrid(!pm.isProjectMemberEdit, pm.projectMemberList);
$scope.updateProjectMembers({ projectMembers: pm.projectMemberList });
pm.isProjectMemberEdit = false;
}
/**
* Function to add a new project member
* #param {*} data
* #param {*} projectMemberDetails
*/
function addProjectMember(data, projectMemberDetails) {
ProjectService.addProjectMember(data).then(function (response) {
if (response.isValid()) {
pm.projectMemberList.splice(0, 0, pm.projectMembersData);
pm.bindDataToGrid(false, pm.projectMemberList);
enableOrDisableEmployee(pm.projectMembersData.EmpID, true);
resetPMForm();
$scope.$emit('evt.update-project-managers', projectMemberDetails);
logger.success('Resource has been added to the project');
} else {
var errorMsg = response.getMessage(
$translate.instant('prj.resource'),
$translate.instant('event.adding')
);
logger.error(errorMsg);
}
});
}
/**
* Function to update a project member's details
* #param {*} data
* #param {*} projectMemberDetails
*/
function updateProjectMember(data, projectMemberDetails) {
ProjectService.updateProjectMember(data).then(function (response) {
if (response.isValid()) {
angular.extend(
pm.projectMemberList[currentIndex],
pm.projectMembersData
);
pm.pmFormBtn = $translate.instant('btn.add');
pm.bindDataToGrid(pm.isProjectMemberEdit, pm.projectMemberList);
enableOrDisableEmployee(pm.projectMembersData.EmpID, true);
$scope.$emit('evt.update-project-managers', projectMemberDetails);
resetPMForm();
pm.isProjectMemberEdit = false;
logger.success("Project member's details have been updated.");
} else {
var errorMsg = response.getMessage(
$translate.instant('prj.project_members_details'),
$translate.instant('event.updating')
);
logger.error(errorMsg);
}
});
}
/**
* Function to be executed in the project details form
*/
function membersEditProjectForm() {
var projectMemberDetails = {
empID: pm.projectMembersData.EmpID,
name: pm.projectMembersData.ProjectMember,
isProjectManager: pm.projectMembersData.IsProjectManager,
};
var members = [];
// Adding the projectCode to project member's data
pm.projectMembersData.ProjectCode = $stateParams.projectID;
// Creating the UserID property as the add and update project members API methods expects the UserID and not
// the EmpID
pm.projectMembersData.UserID = pm.projectMembersData.EmpID;
// Adding the current project memeber to the members array as the API methods for the
// add and update project member expects an array
members.push(pm.projectMembersData);
if (pm.isProjectMemberEdit) {
updateProjectMember(members, projectMemberDetails);
} else {
addProjectMember(members, projectMemberDetails);
}
}
pm.eleFocus = function () {
FormHelperService.searchElementFocus();
};
// Clearing the searched item when closing the dropdown
pm.clearSearchTerm = function () {
pm.projectMemberSearchText = '';
};
/**
* return the search results for auto complete controls.
*/
pm.querySearch = function (
query,
list,
listObjProp,
listObjPropName,
splitObjProp
) {
if (!list || list === '') {
list = [];
}
if (listObjPropName) {
var queryObj = {};
queryObj[listObjPropName] = query;
if (splitObjProp) {
var listOjProp = listObjProp.split('.');
pm[listOjProp[0]][listOjProp[1]] = $filter('filter')(
list,
queryObj
);
} else {
pm[listObjProp] = $filter('filter')(list, queryObj);
}
} else {
pm[listObjProp] = $filter('filter')(list, query);
}
};
// Fetching the row and row index when clicking on edit button and showing the details in form
angular.element('table').on('click', '.edit-project-member', function () {
pm.projectMembersData = $scope.dtApiProjectMembers.getRowData(
this.parentElement
);
pm.IsProjectManager = pm.projectMembersData.IsProjectManager;
if (pm.projectMembersData.EmpCostPerHour) {
pm.projectMembersData.EmpCostPerHour =
typeof pm.projectMembersData.EmpCostPerHour === 'string'
? pm.projectMembersData.EmpCostPerHour
: pm.projectMembersData.EmpCostPerHour.toFixed(2);
}
if (pm.projectMembersData.CostPerHour) {
pm.projectMembersData.CostPerHour =
typeof pm.projectMembersData.CostPerHour === 'string'
? pm.projectMembersData.CostPerHour
: pm.projectMembersData.CostPerHour.toFixed(2);
}
// Adding the code as IsProjectManager property is mandatory and sometimes may not be defined
if (!pm.projectMembersData.IsProjectManager) {
pm.projectMembersData.IsProjectManager = false;
}
angular.copy(pm.projectMembersData, oldProjectMemberData);
pm.isProjectMemberEdit = true;
pm.pmFormBtn = $translate.instant('btn.update');
currentIndex = $scope.dtApiProjectMembers.getRowIndex(
this.parentElement
);
});
// Showing an alert and Deleting the row data
angular
.element('table')
.on('click', '.delete-project-member', function () {
var deleteRowIndex = $scope.dtApiProjectMembers.getRowIndex(
this.parentElement
);
var deleteRowData = $scope.dtApiProjectMembers.getRowData(
this.parentElement
);
showConfirmDialog(deleteRowIndex, deleteRowData);
});
function showConfirmDialog(deleteRowIndex, deleteRowData) {
var confirm = $mdDialog
.confirm({
onComplete: function afterShowAnimation() {
var $dialog = angular.element(
document.querySelector('md-dialog')
);
var $dialogContent = $dialog.find('md-dialog-content');
var $actionsSection = $dialog.find('md-dialog-actions');
var $cancelButton = $actionsSection.children()[0];
var $confirmButton = $actionsSection.children()[1];
angular.element($dialogContent).addClass('custom-confirm-class');
angular.element($confirmButton).addClass('md-raised md-warn');
angular.element($cancelButton).addClass('md-raised');
},
})
.title($translate.instant('prj.confirm_pm_delete'))
.textContent(
'Are you sure you want to delete the selected project member?' +
deleteRowData.ProjectMember
)
.ariaLabel($translate.instant('prj.confirm_pm_delete'))
.ok($translate.instant('bar.delete'))
.cancel($translate.instant('bar.cancel'));
$mdDialog.show(confirm).then(function () {
pm.isProjectMemberEdit = false;
if ($scope.isProjectEdit) {
var projectMemberData = [
{
ProjectCode: $stateParams.projectID,
UserID: deleteRowData.EmpID,
},
];
ProjectService.deleteProjectMember(projectMemberData).then(
function (response) {
if (response.isValid()) {
logger.success(
$translate.instant('prj.project_member_removed_success_msg')
);
deleteProjectMember(deleteRowIndex, deleteRowData);
if (deleteRowData.IsProjectManager) {
$scope.$emit(
'evt.project-manager-removed',
deleteRowData.EmpID.toString()
);
}
} else {
var errorMsg = response.getMessage(
$translate.instant('prj.project_member'),
$translate.instant('event.deleting')
);
logger.error(errorMsg);
}
}
);
} else {
deleteProjectMember(deleteRowIndex, deleteRowData);
$scope.updateProjectMembers({
projectMembers: pm.projectMemberList,
});
}
pm.pmFormBtn = $translate.instant('btn.save');
pm.projectMembersData = {
EmpID: '',
Read: roleConstants.NONE,
Write: roleConstants.NONE,
IsProjectManager: false,
};
});
}
function deleteProjectMember(deleteRowIndex, deleteRowData) {
pm.projectMemberList.splice(deleteRowIndex, 1);
pm.bindDataToGrid(false, pm.projectMemberList);
var oldEmpId = deleteRowData.EmpID;
// Add that element to employees dropdown to be able to select it again
enableOrDisableEmployee(oldEmpId, false);
}
function enableOrDisableEmployee(empId, isEnable) {
for (var j = 0; j < pm.resources.length; j++) {
if (pm.resources[j].EmpID === empId) {
pm.resources[j].isDisabled = isEnable;
return;
}
}
}
pm.isReadPermissionLevelLess = function (level) {
return pm.projectMembersData.Read < level ? true : false;
};
/**
* To change the write permission default value based on the read permission
* Ex : If read - own, then write should not be all
*/
pm.changeWriteDefaultValue = function () {
if (pm.projectMembersData.Read < pm.projectMembersData.Write) {
pm.projectMembersData.Write = pm.projectMembersData.Read;
}
};
/**
* Get the cost per hour of an employee when the employee value is changed
*/
pm.getCostPerHour = function () {
ResourceService.getEmployeeCostPerHour(
pm.projectMembersData.EmpID
).then(
function (response) {
if (response.isValid()) {
var costPerHour = response.getData();
if (costPerHour && costPerHour[0]) {
pm.projectMembersData.EmpCostPerHour =
costPerHour[0].CostPerHour.toFixed(2);
pm.projectMembersData.CostPerHour =
pm.projectMembersData.EmpCostPerHour;
}
}
},
function (error) {
logger.error(error);
}
);
};
$scope.$on("evt.clear-pm-members-grids-data", function () {
pm.projectMemberList = [];
pm.bindDataToGrid(false, pm.projectMemberList);
});
// Binding the data to grid with updated data.
pm.bindDataToGrid = function (reOrder, projectMembers) {
pm.projectMemberList = projectMembers;
if (pm.projectMemberList && pm.projectMemberList.length) {
var currPage = $scope.dtApiProjectMembers.getPageInfo()['page'];
$scope.dtApiProjectMembers.bindData(pm.projectMemberList);
currPage = currPage >= 0 ? currPage : 0;
if (reOrder) {
$scope.dtApiProjectMembers.orderByColumn([[1, 'desc']]);
} else {
$scope.dtApiProjectMembers.setPage(currPage);
}
} else {
$scope.dtApiProjectMembers.bindData([]);
}
};
function resetPMForm() {
$scope.showNoErrorsPerm = true;
$scope.vm.pmData.$setPristine();
$scope.vm.pmData.$setUntouched(true);
pm.projectMembersData = {
EmpID: '',
Read: roleConstants.NONE,
Write: roleConstants.NONE,
IsProjectManager: false,
};
}
$scope.$on('evt.reset-project-members-form', function () {
resetPMForm();
});
}
);
I tried linking data when adding new resource- I can see project getting linked. I hard coded this to see if I was working on the right container.

How to wrap a JS script inside an Angular directive

I am learning AngularJS and I have a conventional JS Script that I wrote a while ago and I would like to use it inside my new Angular app.
Can I literally just dump the entire script in side the directive or do I need to change some things like the keyword this to element etc...?
directive.directive("skillLevel", ['$timeout', function($timeout) {
return{
link: function(scope, el, atts){
// CAN I PASTE MY SCRIPT HERE??
}
}]);
I have this 'quite length some' script that I want to use. How would I go about effectivly using this inside my directive?
(function ($) {
'use strict';
var RSS = function (target, url, options, callback) {
this.target = target;
this.url = url;
this.html = [];
this.effectQueue = [];
this.options = $.extend({
ssl: false,
host: 'www.feedrapp.info',
limit: null,
key: null,
layoutTemplate: '<ul>{entries}</ul>',
entryTemplate: '<li>[{author}#{date}] {title}<br/>{shortBodyPlain}</li>',
tokens: {},
outputMode: 'json',
dateFormat: 'dddd MMM Do',
dateLocale: 'en',
effect: 'show',
offsetStart: false,
offsetEnd: false,
error: function () {
console.log('jQuery RSS: url doesn\'t link to RSS-Feed');
},
onData: function () {},
success: function () {}
}, options || {});
// The current SSL certificate is only valid for *.herokuapp.com
if (this.options.ssl && (this.options.host === 'www.feedrapp.info')) {
this.options.host = 'feedrapp.herokuapp.com';
}
this.callback = callback || this.options.success;
};
RSS.htmlTags = [
'doctype', 'html', 'head', 'title', 'base', 'link', 'meta', 'style', 'script', 'noscript',
'body', 'article', 'nav', 'aside', 'section', 'header', 'footer', 'h1-h6', 'hgroup', 'address',
'p', 'hr', 'pre', 'blockquote', 'ol', 'ul', 'li', 'dl', 'dt', 'dd', 'figure', 'figcaption',
'div', 'table', 'caption', 'thead', 'tbody', 'tfoot', 'tr', 'th', 'td', 'col', 'colgroup',
'form', 'fieldset', 'legend', 'label', 'input', 'button', 'select', 'datalist', 'optgroup',
'option', 'textarea', 'keygen', 'output', 'progress', 'meter', 'details', 'summary', 'command',
'menu', 'del', 'ins', 'img', 'iframe', 'embed', 'object', 'param', 'video', 'audio', 'source',
'canvas', 'track', 'map', 'area', 'a', 'em', 'strong', 'i', 'b', 'u', 's', 'small', 'abbr', 'q',
'cite', 'dfn', 'sub', 'sup', 'time', 'code', 'kbd', 'samp', 'var', 'mark', 'bdi', 'bdo', 'ruby',
'rt', 'rp', 'span', 'br', 'wbr'
];
RSS.prototype.load = function (callback) {
var apiProtocol = 'http' + (this.options.ssl ? 's' : '');
var apiHost = apiProtocol + '://' + this.options.host;
var apiUrl = apiHost + '?callback=?&q=' + encodeURIComponent(this.url);
// set limit to offsetEnd if offset has been set
if (this.options.offsetStart && this.options.offsetEnd) {
this.options.limit = this.options.offsetEnd;
}
if (this.options.limit !== null) {
apiUrl += '&num=' + this.options.limit;
}
if (this.options.key !== null) {
apiUrl += '&key=' + this.options.key;
}
$.getJSON(apiUrl, callback);
};
RSS.prototype.render = function () {
var self = this;
this.load(function (data) {
try {
self.feed = data.responseData.feed;
self.entries = data.responseData.feed.entries;
} catch (e) {
self.entries = [];
self.feed = null;
return self.options.error.call(self);
}
var html = self.generateHTMLForEntries();
self.target.append(html.layout);
if (html.entries.length !== 0) {
if ($.isFunction(self.options.onData)) {
self.options.onData.call(self);
}
self.appendEntriesAndApplyEffects($('entries', html.layout), html.entries);
}
if (self.effectQueue.length > 0) {
self.executeEffectQueue(self.callback);
} else if ($.isFunction(self.callback)) {
self.callback.call(self);
}
});
};
RSS.prototype.appendEntriesAndApplyEffects = function (target, entries) {
var self = this;
$.each(entries, function (idx, entry) {
var $html = self.wrapContent(entry);
if (self.options.effect === 'show') {
target.before($html);
} else {
$html.css({ display: 'none' });
target.before($html);
self.applyEffect($html, self.options.effect);
}
});
target.remove();
};
RSS.prototype.generateHTMLForEntries = function () {
var self = this;
var result = { entries: [], layout: null };
$(this.entries).each(function () {
var entry = this;
var offsetStart = self.options.offsetStart;
var offsetEnd = self.options.offsetEnd;
var evaluatedString;
// offset required
if (offsetStart && offsetEnd) {
if (index >= offsetStart && index <= offsetEnd) {
if (self.isRelevant(entry, result.entries)) {
evaluatedString = self.evaluateStringForEntry(
self.options.entryTemplate, entry
);
result.entries.push(evaluatedString);
}
}
} else {
// no offset
if (self.isRelevant(entry, result.entries)) {
evaluatedString = self.evaluateStringForEntry(
self.options.entryTemplate, entry
);
result.entries.push(evaluatedString);
}
}
});
if (!!this.options.entryTemplate) {
// we have an entryTemplate
result.layout = this.wrapContent(
this.options.layoutTemplate.replace('{entries}', '<entries></entries>')
);
} else {
// no entryTemplate available
result.layout = this.wrapContent('<div><entries></entries></div>');
}
return result;
};
RSS.prototype.wrapContent = function (content) {
if ($.trim(content).indexOf('<') !== 0) {
// the content has no html => create a surrounding div
return $('<div>' + content + '</div>');
} else {
// the content has html => don't touch it
return $(content);
}
};
RSS.prototype.applyEffect = function ($element, effect, callback) {
var self = this;
switch (effect) {
case 'slide':
$element.slideDown('slow', callback);
break;
case 'slideFast':
$element.slideDown(callback);
break;
case 'slideSynced':
self.effectQueue.push({ element: $element, effect: 'slide' });
break;
case 'slideFastSynced':
self.effectQueue.push({ element: $element, effect: 'slideFast' });
break;
}
};
RSS.prototype.executeEffectQueue = function (callback) {
var self = this;
this.effectQueue.reverse();
var executeEffectQueueItem = function () {
var item = self.effectQueue.pop();
if (item) {
self.applyEffect(item.element, item.effect, executeEffectQueueItem);
} else if (callback) {
callback();
}
};
executeEffectQueueItem();
};
RSS.prototype.evaluateStringForEntry = function (string, entry) {
var result = string;
var self = this;
$(string.match(/(\{.*?\})/g)).each(function () {
var token = this.toString();
result = result.replace(token, self.getValueForToken(token, entry));
});
return result;
};
RSS.prototype.isRelevant = function (entry, entries) {
var tokenMap = this.getTokenMap(entry);
if (this.options.filter) {
if (this.options.filterLimit && (this.options.filterLimit === entries.length)) {
return false;
} else {
return this.options.filter(entry, tokenMap);
}
} else {
return true;
}
};
RSS.prototype.getFormattedDate = function (dateString) {
// If a custom formatting function is provided, use that.
if (this.options.dateFormatFunction) {
return this.options.dateFormatFunction(dateString);
} else if (typeof moment !== 'undefined') {
// If moment.js is available and dateFormatFunction is not overriding it,
// use it to format the date.
var date = moment(new Date(dateString));
if (date.locale) {
date = date.locale(this.options.dateLocale);
} else {
date = date.lang(this.options.dateLocale);
}
return date.format(this.options.dateFormat);
} else {
// If all else fails, just use the date as-is.
return dateString;
}
};
RSS.prototype.getTokenMap = function (entry) {
if (!this.feedTokens) {
var feed = JSON.parse(JSON.stringify(this.feed));
delete feed.entries;
this.feedTokens = feed;
}
return $.extend({
feed: this.feedTokens,
url: entry.link,
author: entry.author,
date: this.getFormattedDate(entry.publishedDate),
title: entry.title,
body: entry.content,
shortBody: entry.contentSnippet,
bodyPlain: (function (entry) {
var result = entry.content
.replace(/<script[\\r\\\s\S]*<\/script>/mgi, '')
.replace(/<\/?[^>]+>/gi, '');
for (var i = 0; i < RSS.htmlTags.length; i++) {
result = result.replace(new RegExp('<' + RSS.htmlTags[i], 'gi'), '');
}
return result;
})(entry),
shortBodyPlain: entry.contentSnippet.replace(/<\/?[^>]+>/gi, ''),
index: $.inArray(entry, this.entries),
totalEntries: this.entries.length,
teaserImage: (function (entry) {
try {
return entry.content.match(/(<img.*?>)/gi)[0];
}
catch (e) {
return '';
}
})(entry),
teaserImageUrl: (function (entry) {
try {
return entry.content.match(/(<img.*?>)/gi)[0].match(/src="(.*?)"/)[1];
}
catch (e) {
return '';
}
})(entry)
}, this.options.tokens);
};
RSS.prototype.getValueForToken = function (_token, entry) {
var tokenMap = this.getTokenMap(entry);
var token = _token.replace(/[\{\}]/g, '');
var result = tokenMap[token];
if (typeof result !== 'undefined') {
return ((typeof result === 'function') ? result(entry, tokenMap) : result);
} else {
throw new Error('Unknown token: ' + _token + ', url:' + this.url);
}
};
$.fn.rss = function (url, options, callback) {
new RSS(this, url, options, callback).render();
return this; // Implement chaining
};
})(jQuery);
I think a better way would be to wrap that script in an angular module and load that module as a dependancy in your main app and use it anywhere you see fit.

Refreshing gridpanel after removing newly added record from store

How do I remove a newly added row from a gridpanel? The gridpanel is bound to a store.
I use:
store.remove(record);
store.sync();
It works fine on existing records in the grid, the record is removed from the grid directly, but when I add a record and want to remove it right away, it isn't 'removed' form the grid.
The api is called, so the record is 'removed from the database' and the record is indeed gone when I do e.g. a browser refresh.
Does anyone knows how this works? Thanks in advance.
Store configurations
Ext.define('Iziezie.store.animal.doggywood.animal', {
extend: 'Iziezie.store.animal.animal',
model: 'Iziezie.model.animal.doggywood.animal',
proxy: {
type: 'baseProxy',
api: {
create: '../php/api/doggywood_animals.php?request=create',
read: '../php/api/doggywood_animals.php?request=read',
update: '../php/api/doggywood_animals.php?request=update',
destroy: '../php/api/doggywood_animals.php?request=destroy'
}
}
});
New records is added by form:
var store = gridpanel.getStore();
var model = Ext.ModelMgr.getModel(store.model);
var record = model.create();
store.insert(0, record);
...
frm.loadRecord(record);
On form submit
frm.updateRecord();
var record = frm.getRecord();
record.save();
On remove:
var sm = gridpanel.getSelectionModel();
var record = sm.getLastSelected();
var store = gridpanel.getStore();
store.remove(record);
store.sync();
To force a visual refresh on the grid, you can just call
myGridPanel.getView().refresh();
But this shouldn't be required, the grid should just show whatever is in your store. Can you post a full code sample of what you are doing?
try this to create a new record to grid panel using row editing:
createRecord: function() {
var model = Ext.ModelMgr.getModel('EKOJS.model.m_yourmodel');
var r = Ext.ModelManager.create({
id: '',
text: ''
}, model);
this.getYourgridaliasview().getStore().insert(0, r);
this.getYourgridaliasview().rowEditing.startEdit(0, 0);
},
and to remove the selected record in your grid panel :
deleteRecord: function(dataview, selections) {
var getstore = this.getYourgridaliasview().getStore();
var selection = this.getYourgridaliasview().getSelectionModel().getSelection()[
0];
if (selection) {
Ext.Msg.confirm('Confirmation',
'Are you sure to delete this data: id = "' + selection.data
.id + '"?', function(btn) {
if (btn == 'yes') {
getstore.remove(selection);
getstore.sync();
}
});
}
},
and, the important thing always reload your store after creating record like this :
Ext.Ajax.request({
method: 'POST',
url: '../php/api/doggywood_animals.php?request=create',
params: {
data: jsonData
},
success: function(response) {
e.store.reload({
callback: function() {
var newRecordIndex = e.store.findBy(
function(record, id) {
if (record.get('id') === e.record
.data.id) {
return true;
}
return false;
});
/* me.grid.getView().select(recordIndex); */
me.grid.getSelectionModel().select(
newRecordIndex);
}
});
}
});
The listener of after edit in rowediting plugin i use is like this below :
'afteredit': function(editor, e) {
var me = this;
if ((/^\s*$/).test(e.record.data.id)) {
Ext.Msg.alert('Peringatan', 'Kolom "id" tidak boleh kosong.');
return false;
}
/* e.store.sync();
return true; */
var jsonData = Ext.encode(e.record.data);
Ext.Ajax.request({
method: 'POST',
url: '../php/api/doggywood_animals.php?request=create',
params: {
data: jsonData
},
success: function(response) {
e.store.reload({
callback: function() {
var newRecordIndex = e.store.findBy(
function(record, id) {
if (record.get('id') ===
e.record.data.id
) {
return true;
}
return false;
});
/* me.grid.getView().select(recordIndex); */
me.grid.getSelectionModel().select(
newRecordIndex);
}
});
}
});
return true;
}
May be a little help for you.

Angularjs paging limit data load

I always manage pagination with angular
retrieve all the data from the server
and cache it client side (simply put it in a service)
now I have to cope with quite lot of data
ie 10000/100000.
I'm wondering if can get into trouble
using the same method.
Imo passing parameter to server like
page search it's very annoying for a good
user experience.
UPDATE (for the point in the comment)
So a possible way to go
could be get from the server
like 1000 items at once if the user go too close
to the offset (ie it's on the 800 items)
retrieve the next 1000 items from the server
merge cache and so on
it's quite strange not even ng-grid manage pagination
sending parameters to the server
UPDATE
I ended up like:
(function(window, angular, undefined) {
'use strict';
angular.module('my.modal.stream',[])
.provider('Stream', function() {
var apiBaseUrl = null;
this.setBaseUrl = function(url) {
apiBaseUrl = url;
};
this.$get = function($http,$q) {
return {
get: function(id) {
if(apiBaseUrl===null){
throw new Error('You should set a base api url');
}
if(typeof id !== 'number'){
throw new Error('Only integer is allowed');
}
if(id < 1){
throw new Error('Only integer greater than 1 is allowed');
}
var url = apiBaseUrl + '/' + id;
var deferred = $q.defer();
$http.get(url)
.success(function (response) {
deferred.resolve(response);
})
.error(function(data, status, headers, config) {
deferred.reject([]);
});
return deferred.promise;
}
};
};
});
})(window, angular);
(function(window, angular, undefined) {
'use strict';
angular.module('my.mod.pagination',['my.mod.stream'])
.factory('Paginator', function(Stream) {
return function(pageSize) {
var cache =[];
var staticCache =[];
var hasNext = false;
var currentOffset= 0;
var numOfItemsXpage = pageSize;
var numOfItems = 0;
var totPages = 0;
var currentPage = 1;
var end = 0;
var start = 0;
var chunk = 0;
var currentChunk = 1;
var offSetLimit = 0;
var load = function() {
Stream.get(currentChunk).then(function(response){
staticCache = _.union(staticCache,response.data);
cache = _.union(cache,response.data);
chunk = response.chunk;
loadFromCache();
});
};
var loadFromCache= function() {
numOfItems = cache.length;
offSetLimit = (currentPage*numOfItemsXpage)+numOfItemsXpage;
if(offSetLimit > numOfItems){
currentChunk++;
load();
}
hasNext = numOfItems > numOfItemsXpage;
totPages = Math.ceil(numOfItems/numOfItemsXpage);
paginator.items = cache.slice(currentOffset, numOfItemsXpage*currentPage);
start = totPages + 1;
end = totPages+1;
hasNext = numOfItems > (currentPage * numOfItemsXpage);
};
var paginator = {
items : [],
notFilterLabel: '',
hasNext: function() {
return hasNext;
},
hasPrevious: function() {
return currentOffset !== 0;
},
hasFirst: function() {
return currentPage !== 1;
},
hasLast: function() {
return totPages > 2 && currentPage!==totPages;
},
next: function() {
if (this.hasNext()) {
currentPage++;
currentOffset += numOfItemsXpage;
loadFromCache();
}
},
previous: function() {
if(this.hasPrevious()) {
currentPage--;
currentOffset -= numOfItemsXpage;
loadFromCache();
}
},
toPageId:function(num){
currentPage=num;
currentOffset= (num-1) * numOfItemsXpage;
loadFromCache();
},
first:function(){
this.toPageId(1);
},
last:function(){
this.toPageId(totPages);
},
getNumOfItems : function(){
return numOfItems;
},
getCurrentPage: function() {
return currentPage;
},
getEnd: function() {
return end;
},
getStart: function() {
return start;
},
getTotPages: function() {
return totPages;
},
getNumOfItemsXpage:function(){
return numOfItemsXpage;
},
search:function(str){
if(str===this.notFilterLabel){
if(angular.equals(staticCache, cache)){
return;
}
cache = staticCache;
}
else{
cache = staticCache;
cache = _.filter(cache, function(item){ return item.type == str; });
}
currentPage = 1;
currentOffset= 0;
loadFromCache();
}
};
load();
return paginator;
}
});
})(window, angular);
server side with laravel (All the items are cached)
public function tag($page)
{
$service = new ApiTagService(new ApiTagModel());
$items = $service->all();
$numOfItems = count($items);
if($numOfItems > 0){
$length = self::CHUNK;
if($length > $numOfItems){
$length = $numOfItems;
}
$numOfPages = ceil($numOfItems/$length);
if($page > $numOfPages){
$page = $numOfPages;
}
$offSet = ($page - 1) * $length;
$chunk = array_slice($items, $offSet, $length);
return Response::json(array(
'status'=>200,
'pages'=>$numOfPages,
'chunk'=>$length,
'data'=> $chunk
),200);
}
return Response::json(array(
'status'=>200,
'data'=> array()
),200);
}
The only trouble by now is managing filter
I've no idea how to treat filtering :(

How to update an extjs window on its button click

Currently i am facing the following problem.
I am displaying after successful call of this ajax request.
function callDesignWindow(){
var serviceType = $("#serviceType").val();
alert(serviceType);
var ptId = $("#pt_id").val();
alert(ptId);
getAjaxPage({
url : "/ajax/NewEform/design.do?serviceType=" + serviceType +"&ptId =" + ptId,
successCallback: function (data) {
showDesignWindow(data);
}
});
searchVisible = true;
}
function showDesignWindow(htmlData){
alert(" In the show Design Window");
var designWindow = new Ext.Window({
title: "E-Form Design Phase",
width:650,
autoHeight: true,
id:'designWindow',
html: htmlData,
closable: false,
y: 150,
listeners: {
beforeclose: function () {
searchVisible = false;
}
},
buttons: [
{
text: 'Add Control', handler: function() {
saveFormControl();
}
},
{
text:'Customize', handler: function() {
designWindow.hide();
callCustomWindow();
}
}
]
});
designWindow.show(this);
}
function saveFormControl(){
alert(" add control button clicked");
if (!validateEformData()) return false;
formname= $("#formname").val();
alert(formname);
controlType= $("#controlType").val();
alert(controlType);
label= $("#labelname").val();
alert(label);
dataType= $("#dataType").val();
required= $("#required").val();
serviceType= $("#serviceType").val();
ptId = $("#ptId").val();
if(controlType == 3){
var itemList = [];
$("#selectedItemLists option").each(function(){
itemList.push($(this).val());
});
}
data = "eform_name=" + formname + "&control=" + controlType + "&serviceType=" + serviceType +"&ptId=" + ptId +"&labelName=" +label+ "&dataType=" +dataType+"&required="+required+"&items="+itemList;
alert(data);
$.ajax( {
type : "POST",
url : "/ajax/eformDetails/save.do",
data : data,
cache : false,
dataType : "text/html",
timeout: 40000,
error: function (xhr, err)
{
resolveAjaxError(xhr, err);
},
success : function(data) {
// Ext.getCmp('designWindow').close();
// showDesignWindow(data);
}
});
}
Now on success call of the ajax call ("/ajax/eformDetails/save.do") i want to update the designWindow and reset the values.
please help me in this.
If you want to be able to to manipulate our designWindow after you have already created it, you will need to either maintain a reference to it somewhere, or take advantage of the Ext.getCmp method (I would recommend the latter. For example, in your success function:
success: function () {
var myWindow = Ext.getCmp('designWindow');
//do whatever changes you would like to your window
}

Resources