How to convert nested object to query string in Angularjs - arrays

I want to convert this object:
$scope.foo = {
bar: {
baz: 'foobarbaz'
}
}
to
foo[bar][baz]=foobarbaz
query string.
Also how to convert
$scope.fields = ['id', 'name', 'created_at']
to
fields[]=id&fields[]=name&fields[]=created_at`
Is there any library or function in Angularjs to do this job?

No need to write those serializers yourself, Angular has the one built-in for you. imply inject $httpParamSerializerJQLike service and use it:
$scope.foo = {
foo: {
bar: {
baz: 'foobarbaz'
}
}
};
$scope.fields = {
fields: ['id', 'name', 'created_at']
};
console.log( $httpParamSerializerJQLike($scope.foo) );
// => "foo[bar][baz]=foobarbaz"
console.log( $httpParamSerializerJQLike($scope.fields) );
// => "fields[]=id&fields[]=name&fields[]=created_at"
// (output shown URL-decoded)

Take a look at this
function toPhpQuery(obj) {
return Object.keys(obj).map(key => {
var val = obj[key];
var prefix = encodeURIComponent(key);
return Array.isArray(val)
? _toPhpQueryArray(val, prefix)
: _toPhpQueryObject(val, prefix);
}).join("&");
function _toPhpQueryArray(arr, prefix) {
return arr.map(v => prefix + "[]=" + encodeURIComponent(v)).join("&");
}
function _toPhpQueryObject(value, prefix) {
if (typeof value === "object" && value) {
return Object.keys(value).map(k => _toPhpQueryObject(value[k], prefix + "[" + encodeURIComponent(k) + "]")).join("&");
} else {
return prefix + "=" + encodeURIComponent(value);
}
}
}
console.log(toPhpQuery({
foo: {
bar: {
baz: 'foobarbaz'
}
},
fields: ['id', 'name', 'created_at']
}));

Related

Angular 2 Search Pipe filter objects with array property

I have Angular 2 Search Pipe that filters against an array of Project[]. It works for every property except for one containing an array of strings.
Here is a sample of data model
[{
'Id': 2,
'Title': 'Abc',
'Amount': '200',
'Outcome': ['Outcome 2', 'Outcome 22', 'Outcome 222', 'Outcome 2222']
},
{
'Id': 3,
'Title': 'Abc',
'Amount': '300',
'Outcome': ['Outcome 3', 'Outcome 333', 'Outcome 3333', 'Outcome 33333']
}]
Here is the SearchPipe -
not searching against Outcome array
export class SearchPipe implements PipeTransform {
transform(value, args?): Project[] {
let searchText = new RegExp(args, 'ig');
if (value) {
return value.filter(project => {
if (project) {
return project.Title.search(searchText) !== -1
|| project.Focus.search(searchText) !== -1
|| project.Outcome.forEach(outcome => {
if (outcome.search(searchText) !== -1) {
return true;
}
else {
return false;
}
});
}
});
}
}
}
Any Help would be much appreciated - Thank you!
Your foreach is incorrect. It doesnt return true or false. You can change your pipe to something like this and search if it contains something in the string and then return a boolean accordingly.
Like so:
#Pipe({name: 'Search'})
export class Search implements PipeTransform {
transform(value, args?) {
let searchText = 'test';
if (value) {
return value.filter(project => {
if (project) {
return !project.Outcome.every(outcome => {
return (!outcome.includes(searchText))
});
}
});
}
}
}
Also check the plunker I used to see it working ( https://plnkr.co/edit/ntyDUEwe0HXwjeupqDUr?p=preview )
The problem lies within the forEach loop you do. Returning true or false doesn't do what you expect.
A solution would be to move this logic to a separate function:
export class SearchPipe implements PipeTransform {
transform(value, args?): Project[] {
let searchText = new RegExp(args, 'ig');
if (value) {
return value.filter(project => {
if (project) {
return project.Title.search(searchText) !== -1
|| project.Focus.search(searchText) !== -1
|| this._checkArray(project.Outcome, searchText);
}
});
}
}
_checkArray(arr, search) : boolean {
let found: boolean = false;
arr.forEach(outcome => {
if (outcome.search(search) !== -1) {
return true;
}
})
return found;
}
}
It's untested, and not pretty yet. But you get the general idea

Ag-Grid - Saving columns for future use

I am using the ag-grid for angular1, (and loving it), and I want my users to be able to reorgenize columns, change sortings, and everything, and that it will stay after a refresh.
It should not be very hard, except that the columns are circular (contains pointers to themselves), and thus I cannot parse them.
Code:
var columnDefsKey = "columnDefs["+$rootScope.page+"]";
var savedColumns = localStorage.getItem(columnDefsKey);
function saveColumnsState() {
var currentCol = vm.gridOptions.columnApi.getAllColumns();
if (!angular.equals(currentCol, savedColumns))
try {
localStorage.setItem(columnDefsKey, JSON.stringify(currentCol));
} catch (ex) {
log(ex);
log(currentCol);
}
}
And:
onColumnEverythingChanged: saveColumnsState,
onColumnVisible: saveColumnsState,
onColumnPinned: saveColumnsState,
onColumnResized: saveColumnsState,
onColumnRowGroupChanged: saveColumnsState,
onColumnValueChanged: saveColumnsState,
onColumnMoved: saveColumnsState,
onColumnGroupOpened: saveColumnsState,
It fails on the "try" every time:
TypeError: Converting circular structure to JSON(…) [Column, Column, Column, Column, Column, Column, Column, Column, Column, Column]
How can I do that? (save columns for later use)
If I manage to do that, I will be able to create several views without coding.
you can get the better understanding of the issue from below link
Chrome sendrequest error: TypeError: Converting circular structure to JSON
Also check below reference
https://github.com/isaacs/json-stringify-safe
The way to achieve this was to build my own column model, that I can save and parse again, and in which to save only necessary properties.
This method is XSS vulnerable, as I am evaluating functions, but it is a working solution.
columnsApi: {
key: null,
grid: null,
newColumnModel: {
headerName: "",
width: 200,
valueGetter: "",
filter: 'text',
aggFunc: 'none',
filterParams: {apply: true}
},
setKey: function (key) {
this.key = key;
},
setGrid: function (grid) {
this.grid = grid;
},
format: function (columns) {
var format = [];
angular.forEach(columns, function (col) {
var colDef = {
width: col.actualWidth,
pinned: col.pinned,
hide: !col.visible
};
format.push(angular.extend(col.colDef, colDef));
});
return format;
},
getIDs: function (columns) {
var ids = [];
angular.forEach(columns, function (col) {
ids.push(col.colId);
});
return ids;
},
stringify: function (columns) {
return JSON.stringify(columns, function (key, value) {
if (typeof value === "function")
return "/Function(" + value.toString() + ")/";
return value;
});
},
parse: function (string) {
return JSON.parse(string, function (key, value) {
if (typeof value === "string" &&
value.startsWith("/Function(") &&
value.endsWith(")/")) {
value = value.substring(10, value.length - 2);
return eval("(" + value + ")");
}
return value;
});
},
add: function (column) {
if (this.grid === null) {
console.error("Assertion error: grid must not be null");
return;
}
if(column.aggFunc == 'none')
column.aggFunc = undefined;
var groups = this.get().groups;
var newColumns = this.format(getGridColumns(this.grid));
newColumns.push(column);
this.grid.api.setColumnDefs(newColumns);
this.setGroups(groups);
},
save: function () {
var self = this;
if (this.key === null) {
console.error("Assertion error: key must not be null");
return;
}
if (this.grid === null) {
console.error("Assertion error: grid must not be null");
return;
}
var savedOptions = {
columns: self.format(getGridColumns(self.grid)),
groups: self.getIDs(self.grid.columnApi.getRowGroupColumns()),
sorting: self.grid.api.getSortModel(),
filter: self.grid.api.getFilterModel()
};
localStorage.setItem(this.key, this.stringify(savedOptions));
},
// Get function uses "eval" - XSS vulnerable.
get: function () {
if (this.key === null) {
console.error("Assertion error: key must not be null");
return;
}
var options = localStorage.getItem(this.key);
if (options)
options = this.parse(options);
return options;
},
remove: function (field) {
if (this.grid === null) {
console.error("Assertion error: grid must not be null");
return;
}
var newColumns = this.format(getGridColumns(this.grid));
angular.forEach(newColumns, function (col, key) {
if (col.field == field)
newColumns.splice(key, 1);
});
this.grid.api.setColumnDefs(newColumns);
},
setGroups: function (groups) {
var self = this;
angular.forEach(groups, function (id) {
angular.forEach(getGridColumns(self.grid), function (col) {
if (col.colId == id)
self.grid.columnApi.addRowGroupColumn(col);
});
});
}
}
This solution was written for Ag-Grid 5 I believe, and thus I am not sure if it still holds.

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.

Multiple select2 angularUI load remote data

I have an issue with loading remote data in multiple select2. My code is
var fetchGroups = function (queryParams) {
console.log(JSON.stringify(queryParams));
return $http.get("https://******/****/***/" + queryParams.data.query).then(queryParams.success);
};
$scope.groupSelectOptions= {
minimumInputLength: 3,
ajax: {
data: function (term, page) {
return { query: term };
},
quietMillis: 500,
transport: fetchGroups,
results: function (data, page) {
console.log(data);
// parse the results into the format expected by Select2 return { results: data };
var drastics = data.data.result;
if(drastics){
var data = new Array();
for(var i = 0; i < drastics.length; i++){
data.push(
{
id: drastics[i].id,
text: drastics[i].name
}
);
}
} else {
data = data.data.result;
}
return { results: data };
}
}
};
It returns the values from the get request but when i select it returns undefined at the input box.
Just make sure you've included the 'data' property to the $scope.groupSelectOptions like so :
$scope.groupSelectOptions= {
minimumInputLength: 3,
ajax: {
data: function (term, page) {
return { query: term };
},
.....
data:[]}
You should now see the term selected in the input field.

ExtJs 4.2 Extend Custom Model using MVC problems

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.

Resources