Sencha Touch store filterBy function - javascript

Hi I am trying to work with the store filterBy function but i am unable to make it work as I want.
I have four buttons(A B C D) and a list with all data related to buttons
When I click on the button I should filter accordingly
Note:- when I click A ,I should get records of A
when I click B , I should get records of B appended to A's list of records
So actually when I click on the buttons I should have a array of button ids and filter the the list using these id's.
filterList:function (list, index, target, record){
var categories=[];
categories.push(record.get('id'));
for(c=0;c<categories.length;c++)
{
Ext.getStore('mystore').filterBy(function(record){
var id = record.get('id');
if(id==categories[c])
{
return true;
}
});
}
}
Any help is appreciated.

What is wrong with your code
The filterBy return function should always return a boolean value. You are only returning true, and no false. Besides that you are filtering the store in a loop, and the parameter record exists twice (as a parameter in the function filterList and in the return function of the filterBy).
Example
I created a Fiddle to show you where I came up with. I know it is ExtJs instead of Sencha Touch, but you will get the idea. I will step through the MainController, where all the logic is.
I didn't clean the code so there is some duplication, but it's just a concept.
Setting up some logic
First I create a set of buttons on my view. See that I'm setting an action property.
...
tbar: [{
text: 'Filter a',
action: 'a'
}, {
text: 'Filter b',
action: 'b'
}],
...
Then I bind an onClick event to the button. In this event I use the action property as a searchValue, but it could be anything of course.
...
onClick: function(button, event, eOpts) {
var me = this,
grid = me.getMainGrid(),
store = grid.getStore(),
filters = store.getFilters(),
searchValue = button.action,
regex = RegExp(searchValue, 'i'),
filter = new Ext.util.Filter({
id: button.id,
filterFn: function(record) {
var match = false;
Ext.Object.each(record.data, function(property, value) {
match = match || regex.test(String(value));
});
return match;
}
});
if (filters.containsKey(button.id)) {
store.removeFilter(filter);
} else {
store.addFilter(filter);
}
},
...
The magic
The magic is in the filter instance. By adding new filter instances each time you filter, you can filter with several filters. If you push button a and button b they will respect each other. In that filter I use a regex to search through all data of the current model. I config an id to recognize the filter so I can remove it afterwards.
filter = new Ext.util.Filter({
id: button.id,
filterFn: function(record) {
var match = false;
Ext.Object.each(record.data, function(property, value) {
match = match || regex.test(String(value));
});
return match;
}
});
If the filter doesn't exists it will be added, otherwise it will be removed.
if (filters.containsKey(button.id)) {
store.removeFilter(filter);
} else {
store.addFilter(filter);
}
Reset filters
I also created a textfield to search through all data. Instead of adding and removing filters I just call clearFilter and add a new filter with new searchvalue.
onKeyUp: function(textField, event, eOpts) {
this.filterStore(textField.getValue());
},
filterStore: function(searchValue) {
var me = this,
grid = me.getMainGrid(),
store = grid.getStore(),
regex = RegExp(searchValue, 'i');
store.clearFilter(true);
store.filter(new Ext.util.Filter({
filterFn: function(record) {
var match = false;
Ext.Object.each(record.data, function(property, value) {
match = match || regex.test(String(value));
});
return match;
}
}));
}
The complete maincontroller
Ext.define('Filtering.controller.MainController', {
extend: 'Ext.app.Controller',
config: {
refs: {
mainGrid: 'maingrid'
}
},
init: function() {
var me = this;
me.listen({
global: {},
controller: {},
component: {
'segmentedbutton': {
toggle: 'onToggle'
},
'toolbar > button': {
click: 'onClick'
},
'textfield': {
keyup: 'onKeyUp'
}
},
store: {
'*': {
metachange: 'onMetaChange',
filterchange: 'onFilterChange'
}
},
direct: {}
});
},
onLaunch: function() {
var store = Ext.StoreManager.lookup('Users') || Ext.getStore('Users');
store.load();
},
onMetaChange: function(store, metaData) {
var grid = this.getMainGrid(),
model = store.getModel(),
// metadata
fields = metaData.fields,
columns = metaData.columns,
gridTitle = metaData.gridTitle;
model.fields = fields;
grid.setTitle(gridTitle);
grid.reconfigure(store, columns);
},
onFilterChange: function(store, filters, eOpts) {
var me = this,
grid = me.getMainGrid();
grid.getSelectionModel().select(0);
},
/**
* Used for the segmented buttons
*/
onToggle: function(container, button, pressed) {
var me = this,
grid = me.getMainGrid(),
store = grid.getStore(),
//filters = store.getFilters(),
searchValue = button.action,
regex = RegExp(searchValue, 'i'),
filter = new Ext.util.Filter({
id: button.id,
filterFn: function(record) {
var match = false;
Ext.Object.each(record.data, function(property, value) {
match = match || regex.test(String(value));
});
return match;
}
});
if (pressed) {
store.addFilter(filter);
} else {
store.removeFilter(filter);
}
},
/**
* Used for the toolbar buttons
*/
onClick: function(button, event, eOpts) {
var me = this,
grid = me.getMainGrid(),
store = grid.getStore(),
filters = store.getFilters(),
searchValue = button.action,
regex = RegExp(searchValue, 'i'),
filter = new Ext.util.Filter({
id: button.id,
filterFn: function(record) {
var match = false;
Ext.Object.each(record.data, function(property, value) {
match = match || regex.test(String(value));
});
return match;
}
});
if (filters.containsKey(button.id)) {
store.removeFilter(filter);
} else {
store.addFilter(filter);
}
},
/**
* Used for the textfield
*/
onKeyUp: function(textField, event, eOpts) {
this.filterStore(textField.getValue());
},
filterStore: function(searchValue) {
var me = this,
grid = me.getMainGrid(),
store = grid.getStore(),
regex = RegExp(searchValue, 'i');
store.clearFilter(true);
store.filter(new Ext.util.Filter({
filterFn: function(record) {
var match = false;
Ext.Object.each(record.data, function(property, value) {
match = match || regex.test(String(value));
});
return match;
}
}));
}
});
The complete view
Ext.define('Filtering.view.MainGrid', {
extend: 'Ext.grid.Panel',
xtype: 'maingrid',
tbar: [{
xtype: 'segmentedbutton',
allowMultiple: true,
items: [{
text: 'Filter a',
action: 'a'
}, {
text: 'Filter b',
action: 'b'
}]
}, {
text: 'Filter a',
action: 'a'
}, {
text: 'Filter b',
action: 'b'
}, {
xtype: 'textfield',
emptyText: 'Search',
enableKeyEvents: true
}],
//title: 'Users', // Title is set through the metadata
//store: 'Users', // we reconfigure the store in the metachange event of the store
columns: [] // columns are set through the metadata of the store (but we must set an empty array to avoid problems)
});

Assuming you have two toggle buttons and you want to filter store on toggling of those buttons,
Controller
Ext.define('namespace',{
extend:'controller...',
config:{
refs:{
btnA:'#btnA',
btnB:'#btnB',
},
controls:{
btnA:{
change:'btnChange'
},
btnB:{
change:'btnChange'
}
}
},
btnChange:function(ths,val){
var btnA = this.getBtnA().getValue(),
btnB = this.getBtnB().getValue();
Ext.getStore('mystore').filterBy(function(r){
if(btnA && btnB){
return r.get('id') === btnA.getValue() || r.get('id') === btnB.getValue();
}else if(btnA){
return r.get('id') === btnA.getValue();
}else if(btnB){
return r.get('id') === btnB.getValue();
}
return false;
});
}
});

Related

How do I use Vue-draggable and Vuex to dynamically split up one list into multiple lists?

I have an array that takes input from the user from answering multiple questions. These values are stored in my vuex store and the results are displayed on screen in a draggable list.
computed: {
allValues() {
const val1 = this.responses1
const val2 = this.responses2
const val3 = this.responses3
const val4 = this.responses4
const val5 = this.responses5
const val6 = this.responses6
const val7 = this.responses7
const coreValues = val1.concat(val2,val3,val4,val5,val6,val7)
this.$store.dispatch('corevalues/loadCoreValues', coreValues)
return this.$store.getters['corevalues/getCoreValues']
}
}
Draggable List
<draggable :v-model="allValues"
options:='group: "allValues"'>
<transition-group>
<div v-for="val in allValues" :key="val.value">
{{val.value}}
</div>
</transition-group>
</draggable>
{{ allValues }}
However, on screen although I can drag and sort the values - they do not reorder in the Vuex Store, only on-screen.
1) I need them to re-order in the store.
2) Although a single array is created through the user input I require users to be able to drag values into a second or even a third column in order to group them.
How do I make it so my on screen changes are reflected in the store - even in a new array - and so that my list can be split up into multiple columns?
This my my Code Sandbox: https://codesandbox.io/embed/vue-template-j53g3
EDIT: After Sabee response
I have implemented the following code:
watch:{
allValues: {
handler: function(newValue) {
console.log('here', newValue)
this.$store.dispatch("corevalues/loadCoreValues", newValue);
}
},
deep: true // deep watching changes
},
But as the image below shows - the arary {{ allValues }} is still in the same order even though it has been re-arranged on screen.
2nd edit
Updated code as advised.
Console is logging 'Drag Ended' but as the screenshot below shows the Core Values in the store has not updated - this is after 'reloading state' via dev tools.
You can use
watch:{
list: {
handler: function(newValue) {
// do your job
// this.$store.commit("updateList", value);
// commit your changes to store
}
},
deep: true // deep watching changes
}
}
for checking changes and re-orders, also good solution create a button for saving user changes to store.
UPDATE
So drag changes not wathed :( ...
But there are events in vue-draggable #end
On drag end you can store sorted array in vuex store
<draggable :v-model="allValues" #end="onEnd">
<transition-group>
<div v-for="val in allValues" :key="val.value">{{val.value}}</div>
</transition-group>
</draggable>
And in methods
methods: {
onEnd(){
console.log("Drag ended")
this.$store.dispatch("corevalues/loadCoreValues", this.allValues);
},
Finally
<script>
import draggable from "vuedraggable";
export default {
components: {
draggable
},
data() {
return {
num: 1,
allValues:[],
responses1: [],
responses2: [],
responses3: [],
responses4: [],
responses5: [],
responses6: [],
responses7: [],
question: [
{
id: 1,
question: "What do you believe defines the culture at your company?"
},
{
id: 2,
question:
"What values do you bring to your work that you consistently uphold whether or not they are rewarded?"
},
{
id: 3,
question:
"What do you truly stand for in your work? What do you believe your company truly stands for?"
},
{
id: 4,
question:
"What do your customers believe about you? What do they believe you stand for?"
},
{
id: 5,
question:
"What values does your company consistently adhere to in the face of obstacles?"
},
{
id: 6,
question: "What are your company’s greatest strengths?"
},
{
id: 7,
question:
"What are the top three to five most important behaviours you should expect from every employee (including you)?"
}
]
};
},
computed: {
number(number) {
return this.number + number;
},
// allValues: {
// // get() {
// // const val1 = this.responses1;
// // const val2 = this.responses2;
// // const val3 = this.responses3;
// // const val4 = this.responses4;
// // const val5 = this.responses5;
// // const val6 = this.responses6;
// // const val7 = this.responses7;
// // const coreValues = val1.concat(val2, val3, val4, val5, val6, val7);
// // // this.$store.dispatch("corevalues/loadCoreValues", coreValues);
// // // return this.$store.getters["corevalues/getCoreValues"];
// // return coreValues;
// // },
// }
},
watch: {
responses1: {
handler: function(newValue) {
console.log(newValue)
this.appendWithoutDublicates(this.responses1)
},
deep: true // deep watching changes if you need
},
// responses from 2 to 7: {
// handler: function(newValue) {
// console.log(newValue)
// this.appendWithoutDublicates(this.responses1)
// },
// deep: true // deep watching changes if you need
// },
allValues: {
handler: function(newValue) {
console.log(newValue)
this.$store.dispatch("corevalues/loadCoreValues", newValue);
},
deep: true // deep watching changes if you need
},
},
methods: {
appendWithoutDublicates(values){
this.allValues = this.allValues.concat(values.filter(item => {
return this.allValues.findIndex(obj => obj.value === item.value) < 0;
}));
},
onEnd() {
console.log("Drag ended");
console.log(this.allValues);
this.$store.dispatch("corevalues/loadCoreValues", this.allValues);
},
setValues() {
// this.allValues = coreValues
},
questionNumber(num) {
this.num += num;
},
addresponse1: function() {
var elem = document.createElement("tr");
this.responses1.push({
value: ""
});
},
removeElement1: function(index) {
this.responses1.splice(index, 1);
},
addresponse2: function() {
var elem = document.createElement("tr");
this.responses2.push({
value: ""
});
},
removeElement2: function(index) {
this.responses2.splice(index, 1);
},
addresponse3: function() {
var elem = document.createElement("tr");
this.responses3.push({
value: ""
});
},
removeElement3: function(index) {
this.responses3.splice(index, 1);
},
addresponse4: function() {
var elem = document.createElement("tr");
this.responses4.push({
value: ""
});
},
removeElement4: function(index) {
this.responses4.splice(index, 1);
},
addresponse5: function() {
var elem = document.createElement("tr");
this.responses5.push({
value: ""
});
},
removeElement5: function(index) {
this.responses5.splice(index, 1);
},
addresponse6: function() {
var elem = document.createElement("tr");
this.responses6.push({
value: ""
});
},
removeElement6: function(index) {
this.responses6.splice(index, 1);
},
addresponse7: function() {
var elem = document.createElement("tr");
this.responses7.push({
value: ""
});
},
removeElement7: function(index) {
this.responses7.splice(index, 1);
}
}
};
</script>
And update draggable also
<draggable :list="allValues" #end="onEnd">
<transition-group>
<div v-for="val in allValues" :key="val.value">{{val.value}}</div>
</transition-group>
</draggable>

Lodash/JS - Convert _.find statement to _.forEach

I'm having trouble converting the following Lodash statement to something that works in an application that I inherited at work and am trying to fix bugs in. At the moment, we are having issues with only one device on our system returning when two devices have the same name and the following code seems to be the culprit as it would only return the first "true" value in an array:
var group = _.find(groupList, {id: id});
How would I successfully convert this to a statement that iterates over all objects in an array and then returns those objects? I've tried the following options to no avail:
var group = _.filter(groupList, {id: id});
and
var group = _.every(groupList, {id: id});
and
var group = _.forEach(groupList, {id: id})
return {id};
I know I am probably missing something in my syntax. Any help would be much appreciated. Running Lodash v3.7.0
Here's the rest of the code in the directive in case anyone is interested or sees something else I might be missing:
define(['./../_module'], function (directives) {
'use strict';
directives.directive('dmGroupedList', ['$compile', '$state', 'APP_CONSTANTS', function ($compile, $state, APP_CONSTANTS) {
return {
restrict: 'A',
scope: {
items: '=',
groupBy: '=',
actions: '=',
nonameGroupLabel: '='
},
templateUrl: function (elem, attrs) {
return attrs.templateUrl || 'views/shared-templates/grouped-list.html';
},
link: function (scope, element, attrs) {
scope.$watchGroup(['items', 'groupBy', 'nonameGroupLabel'], function () {
scope.groupList = [];
scope.groupedItems = {};
var actions = scope.actions[scope.groupBy];
_.forEach(scope.items, function (item) {
scope.handlers.getGroups(scope.groupList, item, scope.items, scope.groupBy, actions);
});
_.forEach(scope.groupList, function (group) {
var items = scope.groupedItems[group.id];
items = _.sortBy(items, function (item) {
return item.description;
});
scope.groupedItems[group.id] = items;
});
var groupsToSort = _.where(scope.groupList, {unassigned: false});
var unassignedGroups = _.sortBy(_.where(scope.groupList, {unassigned: true}), 'name');
scope.groupList = _.sortBy(groupsToSort, function (group) {
return group.name;
});
//adds unassigned groups to a new array via the javascript "push" method
if (angular.isDefined(unassignedGroups)) {
for (var i = 0; i < unassignedGroups.length; i++) {
scope.groupList.push(unassignedGroups[i]);
}
}
});
scope.handlers = {
getGroups: function (groupList, item, items, groupBy, actions) {
var group = item[groupBy];
if (_.isEmpty(group)) {
scope.handlers.addGroupToList(groupList, APP_CONSTANTS.DEVICE_NONE_NAME_MAPPING.NONE, items, groupBy, item, actions, scope);
}
else {
if (angular.isArray(group) || angular.isObject(group)) {
_.forEach(group, function (groupName) {
if (groupName == APP_CONSTANTS.ZERO) {
scope.handlers.addGroupToList(groupList, APP_CONSTANTS.DEVICE_NONE_NAME_MAPPING.NONE, items, groupBy, item, actions, scope);
return;
}
scope.handlers.addGroupToList(groupList, groupName, items, groupBy, item, actions, scope);
})
} else {
scope.handlers.addGroupToList(groupList, group, items, groupBy, item, actions, scope);
}
}
},
addGroupToList: function (groupList, groupId, items, groupBy, item, handlers, scope) {
var id = _.camelCase(groupId);
var group = _.find(groupList, {id: id});
//var group = _.forEach(groupList, {id: id})
//return {id};
if (!group) {
var name = '';
var unassigned = false;
var link = null;
if (groupId == APP_CONSTANTS.DEVICE_NONE_NAME_MAPPING.NONE || groupId == APP_CONSTANTS.DEVICE_NONE_NAME_MAPPING.NONE_PARENT_ID) {
if (groupId == APP_CONSTANTS.DEVICE_NONE_NAME_MAPPING.NONE_PARENT_ID) {
name = APP_CONSTANTS.DEVICE_NONE_NAME_MAPPING.NONE;
} else {
name = APP_CONSTANTS.DEVICE_NONE_NAME_MAPPING.UNASSIGNED;
}
unassigned = true;
} else {
link = handlers.getGroupLink(groupId);
name = handlers.getGroupName(groupId, items);
}
group = {id: id, name: name, unassigned: unassigned, link: link};
groupList.push(group);
}
scope.groupedItems[group.id] = scope.groupedItems[group.id] || [];
if (angular.isDefined(handlers.processingGroup)) {
handlers.processingGroup(group, groupList, groupId, items, groupBy, item, handlers, scope);
} else {
scope.groupedItems[group.id].push({
description: handlers.getItemDescription(item),
link: handlers.getItemLink(item)
})
}
}
};
}
};
}]);
});
You can just use filter:
var group = groupList.filter((group) => group.id === id);
EDIT: to return only the element, and not an array, when there is only one match, you can do the following:
var checkSingle = (groups) => groups.length === 1 ? groups[0] : groups;
var group = checkSingle(groupList.filter((group) => group.id === id));
You can _(groupList).groupBy('id').get(id):
var groupList = [
{ id: 1, name: 'site' },
{ id: 2, name: 'test' },
{ id: 2, name: 'prod' },
{ id: 3, name: 'dev' },
{ id: 4, name: 'back' },
{ id: 4, name: 'front' },
{ id: 5, name: 'sprint' }
];
console.log(_(groupList).groupBy('id').get(2));
console.log(_(groupList).groupBy('id').get(3));
console.log(_(groupList).groupBy('id').get(4));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Add editable dynamic objects to an array in Mithriljs

I have an array, that I need to populate with multiple 'properties', something like this:
[
{
name: 'Date',
value: '27 Oct'
},
{
name: 'Type',
value: 'Image'
},
{
name: 'Client',
value: 'Apple'
}
]
I want to list out all the properties in ul and I want to have a + button, that will add a new object to an array (initially name and value will be blank). After double clicking on each item (li in this case), I want to make these properties editable.
So I did something like this:
var Properties = {};
Properties.items = [
{
name: m.prop('Date'),
value: m.prop('21 Dec'),
editable: m.prop(false)
}
];
This is my initial array.
Then, I have a controller:
Properties.controller = function() {
this.addNewItem = function() {
Properties.items.push({
name: m.prop('Sample'),
value: m.prop('Test'),
editable: m.prop(false)
})
};
this.toggleEditable = function(item) {
item.editable(!item.editable());
console.log(item.editable());
};
};
My view:
Properties.view = function(ctrl) {
return m('ul.list-unstyled', [
Properties.items.map(function(item) {
return m('li', [
item.editable() ? m('input', {
value: item.name(),
onkeyup: function(e) {
if(e.keyCode == 13) {
ctrl.toggleEditable.bind(ctrl, item);
} else {
m.withAttr('value', item.name)
}
}
}) :
m('span', {
ondblclick: ctrl.toggleEditable.bind(ctrl, item)
}, item.name()),
m('span', ': '),
m('span', item.value())
]);
}),
m('div',{
onclick: ctrl.addNewItem.bind(ctrl)
}, '+')
]);
};
And finally:
m.mount(document.querySelector('.container'), Properties);
But when I start typing, it sort of overwrites what I wrote and doesn't save the new value..
Any ideas, anyone?
You should keep your original array as the data model, pass it to Properties and let Properties store only the editable state. That is a nice data separation and will simplify the code. It may fix the save problem as well, since it can just set the array value directly in the onkeyup event.
For the overwrite problem, maybe adding a key attribute will work? It seems related. Check out http://mithril.js.org/mithril.html#dealing-with-focus for more information.

Backbone model when created already has attributes

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?

Constructing fuelux datagrid datasource with custom backbone collection

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.

Categories

Resources