How to make local variable to global?
Ext.define('A.view.Management', {
extend: 'Ext.container.Container',
requires: [
'A.store.Management',
],
border: false,
chart: null,
hrer: [],
initComponent: function () {
var me = this;
me.jobStore2 = Ext.create('O2a.store.Management');
Ext.Ajax.request({
url: utils.createUrl('api', 'ard-read'),
async: true,
callback: function(opts, success, response) {
try {
if (success) {
var output = App.decodeHttpResp(response.responseText);
const data = output.data;
let myArr = [];
data.map((date) =>
myArr = Object.keys(date).filter(key => key != 'DATE'));
me.hrer =myArr;
console.log(me.hrer);
if (output.success) {
//return output.success;
} else {
//return output.error;
}
} else {
//return 'Unknown Reason';
}
} catch (ex) {
//return ex;
}
}
});
console.log(me.hrer);
I want to take hrer array to outside. When I console.log it outside the ajax request I am getting an empty array which I have defined as globally. I couldn't pass the values which getting inside the ajax request to outside
In ExtJS 4, we used to do:
Ext.define('A.store.SharedData', {
singleton: true,
foo: 'bar',
johnDoeAge: 42,
hrer: []
});
Then require it in whichever component you want to use and consume it like:
Ext.define('A.view.Management', {
extend: 'Ext.container.Container',
requires: [
'A.store.Management',
'A.store.SharedData'
],
initComponent: function () {
var me = this;
A.store.SharedData.hrer = [1, 2, ...];
...
}
...
});
In my my application I do something like this to create a new model,
this.model = new App.Models.Organisation;
The code for the model looks like this,
'use strict'
App.Models.Organisation = Backbone.Model.extend({
urlRoot: "http://" + App.API_ROOT + "/organisations",
defaults: {
//members : new App.Collections.Users
},
initialize: function() {
//Gets
var members = this.get('users');
var projects = this.get('projects');
var teams = this.get('teams');
var clients = this.get('clients');
console.log(members);
console.log(projects);
console.log(teams);
console.log(clients);
//Sets
if(members != undefined) {
this.set('members', App App.Collections.Users(members));
} else {
this.set('members', App App.Collections.Users);
}
if(projects != undefined) {
this.set('projects', new App.Collections.Projects(projects));
} else {
this.set('projects', new App.Collections.Projects);
}
if(teams != undefined) {
this.set('teams', new App.Collections.Teams(teams));
} else {
this.set('teams', new App.Collections.Teams);
}
if(clients != undefined) {
this.set('clients', new App.Collections.Clients(clients));
} else {
this.set('clients', new App.Collections.Clients);
}
},
validate: function() {
}
});
However when log the new model where I expect to see empty attributes I get the following:
Why would teams and projects have a value when the model is newly created?
The teams collections looks like this,
'use strict'
App.Collections.Teams = Backbone.Collection.extend({
url: 'http://' + Pops.API_ROOT + '/teams',
model: Pops.Models.Team,
initialize: function() {
var members = this.get('members');
this.set('members', new App.Collections.Users(members));
},
search: function(filterValue) {
var matcher = new RegExp(filterValue);
var found_models = this.filter(function(model) {
return matcher.test(model.get('name'));
});
return found_models;
},
});
and the projects collection like this,
App.Collections.Projects = Backbone.Collection.extend({
url: 'http://' + App.API_ROOT + '/project',
model: App.Models.Project,
sort_key: "name",
sort_order: 1,
parent_filter: false,
filters: [1,2,3],
initialize:function() {
var pm = this.get('projectmanager');
this.set('project_manager', new App.Models.User(pm));
var sp = this.get('salesperson');
this.set('sales_person', new App.Models.User(sp));
this.sortByField('created_at', 'desc');
},
comparator: function (item1, item2) {
var val1 = item1.get(this.sort_key);
var val2 = item2.get(this.sort_key);
if (typeof (val1) === "string") {
val1 = val1.toLowerCase();
val2 = val2.toString().toLowerCase();
}
var sortValue = val1 > val2 ? 1 : -1;
return sortValue * this.sort_order;
},
sortByField: function(fieldName, orderType) {
this.sort_key = fieldName;
this.sort_order = orderType == "desc" ? -1 : 1;
console.log(this.sort_order);
this.sort();
},
sortStatus: function( filters ) {
this.filters = filters;
this.each(function(project){
project.set('visible', _.contains(filters, parseInt(project.get('status'))));
});
},
myProjects: function() {
this.each(function(project){
if(project.get('user_id') == '1' && project.get('organisation_id') == null) {
project.set('visible', true);
} else {
project.set('visible', false);
}
}, this);
},
status: function( status ) {
if(this.parent_filter == false) {
//Filter all projects on the dashboard
this.each(function(project){
project.get('visible', true);
project.set('visible', project.get('status') == String(status) );
});
} else {
//Filter only projects that are currently visible
this.each(function(project) {
if(project.get('visible')) {
project.set('visible', project.get('status') == String(status) );
}
});
}
},
otherProjects: function() {
this.each(function(project){
if(project.get('organisation_id') != null) {
project.set('visible', true);
} else {
project.set('visible', false);
}
}, this);
},
sortBy: function(filterBy, orderBy) {
this.sortByField(filterBy, orderBy);
this.sort();
},
search: function(filterValue) {
var matcher = new RegExp(filterValue);
var found_models = this.filter(function(model) {
return matcher.test(model.get('name'));
});
return found_models;
},
});
I see what's going on now, in your teams collection initialize method you have this line:
this.set('members', new App.Collections.Users(members));`
So this is calling set on a collection which is different from calling set on an individual model.
On a collection set treats the first element as an array of models. You are passing 'members' as the first parameter and this adding a model to the collection with every character in the string as one attribute of that model
On a model, set expects either an attributes hash to be passed or 2 parameters attribute name and value to be passed, and will set the model attributes accordingly.
Basically you cannot treat the collection as an individual model.
If you want to keep a reference to the members from the teams collection, why not keeping a reference like this.members = new App.Collections.Users(members) that you can access from other places in the teams collection?
I'm trying to create a button class that extends an AbstractComponent class using $.extend() but the functions in AbstractComponent aren't available when I'm constructing the button.
The specific error I'm receiving is:
Uncaught TypeError: Object [object Object] has no method 'setOptions'
var Button = {};
var abstract = new AbstractComponent;
$.extend(Button,abstract);
//debugger;
//this.setOptions is available here
Button = function(options) {
'use strict';
var defaultOptions = {
templateName: '#button-tmpl',
title: "Label goes here",
type: "primary",
size: "medium",
disabled: null,
autosave: null,
href: null,
onclick: null
};
//debugger
//this.setOptions is not available here
this.setOptions(options, defaultOptions);
this.checkRequiredKeys('title');
return this;
};
Button.prototype.updateOptions = function() {
var options = this.options;
if (options.href === null) {
options.href = 'javascript:;';
}
if (options.disabled === null) {
options.disabled = 'disabled';
}
if (options.autosave === true) {
options.autosave = 'ping-autosave';
}
};
AbstractComponent.js
var AbstractComponent = function() {
console.log('this will be the constructor for elements extending this class');
};
AbstractComponent.prototype.show = function() {
this.render();
};
AbstractComponent.prototype.close = function() {
// stop listeners and remove this component
this.stopListening();
this.remove();
};
AbstractComponent.prototype.getTemplateName = function() {
return this.options.templateName;
};
AbstractComponent.prototype.checkRequiredKeys = function() {
var errors = new Array();
if (typeof this.getTemplateName() === "undefined") {
errors.push('templateName');
}
for (var i = 0; i < arguments.length; i++) {
if (!this.options.hasOwnProperty(arguments[i])) {
errors.push(arguments[i]);
}
}
if (errors.length > 0) {
throw new Exception("Required property(s) not found:" + errors.join(', ') + " in " + this.toString());
}
};
AbstractComponent.prototype.getElement = function() {
'use strict';
if(!this.options.updated) {
this.updateOptions();
}
return new AbstractView(this.options).render().$el;
};
AbstractComponent.prototype.updateOptions = function() {
this.options.updated = true;
return true;
};
AbstractComponent.prototype.getHtml = function() {
return this.getElement().html();
};
AbstractComponent.prototype.setOptions = function(options, defaultOptions) {
this.options = _.defaults(options, defaultOptions);
};
AbstractComponent.prototype.toString = function() {
return "Component" + this.getTemplateName() + "[id=" + this.options.id + "]";
};
jQuery extend is for moving properties from one (or more) object(s) to another object.
$.extend({}, {
foo: 10,
bar: 20
});
You should use prototypal inheritance isntead
function Button(options) {
'use strict';
var defaultOptions = {
templateName: '#button-tmpl',
title: "Label goes here",
type: "primary",
size: "medium",
disabled: null,
autosave: null,
href: null,
onclick: null
};
//debugger
//this.setOptions is not available here
this.setOptions(options, defaultOptions);
this.checkRequiredKeys('title');
return this;
};
Button.prototype = new AbstractComponent;
I am trying to build datagrid with sorting, searching and paging enabled. Therefore, I am using fuelux-datagrid.
MY backbone view looks like this:
var app = app || {};
$(function ($) {
'use strict';
// The Players view
// ---------------
app.PlayersView = Backbone.View.extend({
template: _.template( $("#player-template").html() ),
initialize: function () {
if(this.collection){
this.collection.fetch();
}
this.listenTo(this.collection, 'all', this.render);
},
render: function () {
this.$el.html( this.template );
var dataSource = new StaticDataSource({
columns: [
{
property: 'playername',
label: 'Name',
sortable: true
},
{
property: 'age',
label: 'A',
sortable: true
}
],
data: this.collection.toJSON(),
delay: 250
});
$('#MyGrid').datagrid({
dataSource: dataSource,
stretchHeight: true
});
}
});
});
The player template just contain the template as given in fuelux datagrid . My routing code somewhere instantiate app.playerview with collection as
new app.PlayersView({
collection : new app.PlayersCollection
}));
My players collection contains list of player model as below
[{
"id":1,
"playername":"rahu",
"age":13
},
{
"id":2,
"playername":"sahul",
"age":18
},
{
"id":3,
"playername":"ahul",
"age":19
}]
My datasource class/function to construct datasoruce with columns and data method is as given in datasource constructor
However, I get the error the " datasource in not defined ". Can anybody help me?
I just wanted to hack the code so that instead of datasource constructed from local data.js in given example, I want to construct the datasource so that it takes data from playercollection.
Also, how to add the one extra column so that we can put edit tag insdie and its should be able to edit the particular row model on clicking that edit.
I have been stucking around these a lot. It would be great help to figure out the answer.
I was stucking around datasource.
I modified the datasource as follows and then it worked.
var StaticDataSource = function (options) {
this._formatter = options.formatter;
this._columns = options.columns;
this._delay = options.delay || 0;
this._data = options.data;
};
StaticDataSource.prototype = {
columns: function () {
return this._columns;
},
data: function (options, callback) {
var self = this;
setTimeout(function () {
var data = $.extend(true, [], self._data);
// SEARCHING
if (options.search) {
data = _.filter(data, function (item) {
var match = false;
_.each(item, function (prop) {
if (_.isString(prop) || _.isFinite(prop)) {
if (prop.toString().toLowerCase().indexOf(options.search.toLowerCase()) !== -1) match = true;
}
});
return match;
});
}
// FILTERING
if (options.filter) {
data = _.filter(data, function (item) {
switch(options.filter.value) {
case 'lt5m':
if(item.population < 5000000) return true;
break;
case 'gte5m':
if(item.population >= 5000000) return true;
break;
default:
return true;
break;
}
});
}
var count = data.length;
// SORTING
if (options.sortProperty) {
data = _.sortBy(data, options.sortProperty);
if (options.sortDirection === 'desc') data.reverse();
}
// PAGING
var startIndex = options.pageIndex * options.pageSize;
var endIndex = startIndex + options.pageSize;
var end = (endIndex > count) ? count : endIndex;
var pages = Math.ceil(count / options.pageSize);
var page = options.pageIndex + 1;
var start = startIndex + 1;
data = data.slice(startIndex, endIndex);
if (self._formatter) self._formatter(data);
callback({ data: data, start: start, end: end, count: count, pages: pages, page: page });
}, this._delay)
}
};
Infact, I just removed following code and its associated braces.
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['underscore'], factory);
} else {
root.StaticDataSource = factory();
}
}(this, function () {
I dont know what exactly the above code is doing an what dependdencies they have over.
I am using jlinq a library for extending linq to json and hence i filter my json data. Consider i have a json data that draws a yui datatable on page load with 100 rows. I am doing a clientside filter which will reduce my json data and i am now redrawing the same datatable. What happens is it works pretty well but with an annoying flickering effect...
I call the below method from onkeyup event of the filter textbox,
function showusersfilter(txt) {
var jsondata = document.getElementById("ctl00_ContentPlaceHolder1_HfJsonString").value;
jsondata = jQuery.parseJSON(jsondata);
var results = jLinq.from(jsondata.Table)
.startsWith("name", txt)
.select();
var jsfilter = { "Table": results };
var myColumnDefs = [
{ key: "userid", label: "UserId", hidden: true },
{ key: "name", label: "Name", sortable: true, sortOptions: { defaultDir: YAHOO.widget.DataTable.CLASS_DESC} },
{ key: "designation", label: "Designation" },
{ key: "phone", label: "Phone" },
{ key: "email", label: "Email" },
{ key: "role", label: "Role", sortable: true, sortOptions: { defaultDir: YAHOO.widget.DataTable.CLASS_DESC} },
{ key: "empId", label: "EmpId" },
{ key: "reportingto", label: "Reporting To", sortable: true, sortOptions: { defaultDir: YAHOO.widget.DataTable.CLASS_DESC} },
{ key: "checkbox", label: "", formatter: "checkbox", width: 20 }
];
var jsonObj = jsfilter;
var target = "datatable";
var hfId = "ctl00_ContentPlaceHolder1_HfId";
generateDatatable(target, jsonObj, myColumnDefs, hfId);
}
My textbox looks
<asp:TextBox ID="TxtUserName" runat="server" CssClass="text_box_height_14_width_150" onkeyup="showusersfilter(this.value);"></asp:TextBox>
and my generatedatatable function,
function generateDatatable(target, jsonObj, myColumnDefs, hfId) {
var root;
for (key in jsonObj) {
root = key; break;
}
var rootId = "id";
if (jsonObj[root].length > 0) {
for (key in jsonObj[root][0]) {
rootId = key; break;
}
}
YAHOO.example.DynamicData = function() {
var myPaginator = new YAHOO.widget.Paginator({
rowsPerPage: 25,
template: YAHOO.widget.Paginator.TEMPLATE_ROWS_PER_PAGE,
rowsPerPageOptions: [10, 25, 50, 100],
pageLinks: 10
});
// DataSource instance
var myDataSource = new YAHOO.util.DataSource(jsonObj);
myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
myDataSource.responseSchema = { resultsList: root, fields: new Array() };
myDataSource.responseSchema.fields[0] = rootId;
for (var i = 0; i < myColumnDefs.length; i++) {
myDataSource.responseSchema.fields[i + 1] = myColumnDefs[i].key;
}
// DataTable configuration
var myConfigs = {
sortedBy: { key: myDataSource.responseSchema.fields[1], dir: YAHOO.widget.DataTable.CLASS_ASC }, // Sets UI initial sort arrow
paginator: myPaginator
};
// DataTable instance
var myDataTable = new YAHOO.widget.DataTable(target, myColumnDefs, myDataSource, myConfigs);
myDataTable.resizeHack = function()
{ this.getTbodyEl().parentNode.style.width = "100%"; }
myDataTable.subscribe("rowMouseoverEvent", myDataTable.onEventHighlightRow);
myDataTable.subscribe("rowMouseoutEvent", myDataTable.onEventUnhighlightRow);
myDataTable.subscribe("rowClickEvent", myDataTable.onEventSelectRow);
myDataTable.subscribe("checkboxClickEvent", function(oArgs) {
var hidObj = document.getElementById(hfId);
var elCheckbox = oArgs.target;
var oRecord = this.getRecord(elCheckbox);
var id = oRecord.getData(rootId);
if (elCheckbox.checked) {
if (hidObj.value == "") {
hidObj.value = id;
}
else {
hidObj.value += "," + id;
}
}
else {
hidObj.value = removeIdFromArray("" + hfId, id);
}
});
myPaginator.subscribe("changeRequest", function() {
if (document.getElementById(hfId).value != "") {
if (document.getElementById("ConfirmationPanel").style.display == 'block') {
document.getElementById("ConfirmationPanel").style.display = 'none';
}
document.getElementById(hfId).value = "";
}
return true;
});
myDataTable.handleDataReturnPayload = function(oRequest, oResponse, oPayload) {
oPayload.totalRecords = oResponse.meta.totalRecords;
return oPayload;
}
return {
ds: myDataSource,
dt: myDataTable
};
} ();
}
EDIT:
I even used a delay on the keyup event still the flickering occurs,
var timer;
function chk_me(){
clearTimeout(timer);
timer = setTimeout(function validate(){ showusersfilter(document.getElementById("ctl00_ContentPlaceHolder1_TxtUserName").value);}, 1000);
}
Why do you create a new dataTable each time you filter your data ? You do not need this task. Just supply The filtered data to its dataTable by using sendRequest method of its dataSource
I have create this jsonObject To simulate filtered data
var jsonObject = {
"root":[
{id:"5", userid:"1", name:"ar", designation:"1programmer", phone:"15484-8547", email:"1arthurseveral#yahoo.com.br", role:"1developer", empId:"1789", reportingto:"116"},
{id:"5", userid:"2", name:"br", designation:"2programmer", phone:"25484-8547", email:"2arthurseveral#yahoo.com.br", role:"2developer", empId:"2789", reportingto:"216"},
{id:"5", userid:"3", name:"cr", designation:"3programmer", phone:"35484-8547", email:"3arthurseveral#yahoo.com.br", role:"3developer", empId:"3789", reportingto:"316"},
{id:"5", userid:"4", name:"dr", designation:"4programmer", phone:"45484-8547", email:"4arthurseveral#yahoo.com.br", role:"4developer", empId:"4789", reportingto:"416"},
{id:"5", userid:"5", name:"er", designation:"5programmer", phone:"55484-8547", email:"5arthurseveral#yahoo.com.br", role:"5developer", empId:"5789", reportingto:"516"}
],
"another":[
{id:"5", userid:"5", name:"er", designation:"5programmer", phone:"55484-8547", email:"5arthurseveral#yahoo.com.br", role:"5developer", empId:"5789", reportingto:"516"},
{id:"5", userid:"4", name:"dr", designation:"4programmer", phone:"45484-8547", email:"4arthurseveral#yahoo.com.br", role:"4developer", empId:"4789", reportingto:"416"},
{id:"5", userid:"3", name:"cr", designation:"3programmer", phone:"35484-8547", email:"3arthurseveral#yahoo.com.br", role:"3developer", empId:"3789", reportingto:"316"},
{id:"5", userid:"2", name:"br", designation:"2programmer", phone:"25484-8547", email:"2arthurseveral#yahoo.com.br", role:"2developer", empId:"2789", reportingto:"216"},
{id:"5", userid:"1", name:"ar", designation:"1programmer", phone:"15484-8547", email:"1arthurseveral#yahoo.com.br", role:"1developer", empId:"1789", reportingto:"116"}
]
};
When initializing
(function() {
var Yutil = YAHOO.util,
Ywidget = YAHOO.widget
DataTable = Ywidget.DataTable,
Paginator = Ywidget.Paginator,
DataSource = Yutil.DataSource;
YAHOO.namespace("_3657287"); // QUESTION ID - SEE URL
var _3657287 = YAHOO._3657287;
/**
* paginator
*/
var paginator = new Paginator({
rowsPerPage:25,
template:Paginator.TEMPLATE_ROWS_PER_PAGE,
rowsPerPageOptions:[10, 25, 50, 100],
pageLinks:10
});
/**
* dataSource
*
* As you have static data, I pass an empty "jsonObject" to its constructor
*/
var dataSource = new DataSource({root:[]});
dataSource.responseType = DataSource.TYPE_JSON;
dataSource.responseSchema = {resultsList:"root", fields:[]};
var columnSettings = [
{key:"userid", label:"UserId"},
{key:"name", label:"Name"},
{key:"designation", label:"Designation"},
{key:"phone", label:"Phone"},
{key:"email", label:"Email"},
{key:"role", label:"Role"},
{key:"empId", label:"EmpId"},
{key:"reportingto", label:"Reporting To"}
];
dataSource.responseSchema.fields[0] = "id";
for (var i = 0; i < columnSettings.length; i++) {
dataSource.responseSchema.fields[i + 1] = columnSettings[i].key;
}
/**
* Notice initialLoad equal To false (I suppose your dataTable IS NOT pre-populated)
*/
var dataTableSettings = {
paginator:paginator,
initialLoad:false
};
/**
* dataTable
*
* Notice IT IS STORED in the namespace YAHOO._3657287
*/
_3657287.dataTable = new DataTable("container", columnSettings, dataSource, dataTableSettings);
})();
Now when you want to filter your data, do as follows (Notice sendRequest method)
var i = 0;
YAHOO.util.Event.addListener("reload", "keyup", function(e) {
YAHOO._3657287.dataTable.getDataSource().sendRequest(null, {
success:function(request, response, payload) {
/**
* initializeTable method clear any data stored by The datatable
*/
this.initializeTable();
if(i === 0) {
this.getRecordSet().setRecords(jsonObject["root"], 0);
i++;
} else {
this.getRecordSet().setRecords(jsonObject["another"], 0);
i--;
}
this.render();
},
scope:YAHOO._3657287.dataTable,
argument:null
});
});
You can see here. It works fine!
But if the effect appears again (Notice i am just using relevant part - Nor special feature Nor something else) can occurs because
keyup Event
dataTable rendering
You can set up a variable as follows
var isProcessing = false;
YAHOO.util.Event.addListener("reload", "keyup", function(e) {
if(isProcessing) {
return;
}
isProcessing = true;
YAHOO._3657287.dataTable.getDataSource().sendRequest(null, {
success:function(request, response, payload) {
// as shown above
isProcessing = false;
}
});
}
See also here and here
The problem could be related to the line:
myDataTable.resizeHack = function()
{ this.getTbodyEl().parentNode.style.width = "100%"; }
Since you are resizing the width of the table, it is reasonable to assume that the table will need to be re-painted on the screen resulting in the flicker.