how to use array to store list of contacts - javascript

I am learning angular.js. I am trying to create an app with gmail chat box like implementation. So as a first step I created an implementation where you can create groups and add members from the available contacts array.
First I will show all group available if you click on add group I will show you list of contacts from where you can click on the particular contact I will take the index and add it to new array and then push it into a my contact array.
Here is part of my code
app.factory('contactfactory', function (){
var factory = {};
factory.contacts = [
{email:"vicky-1"},
{email:"vicky2"},
{email:"vicky3"},
{email:"vicky4"},
{email:"vicky5"},
{email:"vicky6"},
{email:"vicky7"},
{email:"vicky8"},
{email:"vicky9"},
{email:"vicky10"},
{email:"vicky11"},
{email:"vicky12"},
{email:"vicky13"},
{email:"vicky14"},
{email:"vicky15"},
{email:"vicky16"},
{email:"vicky17"},
{email:"vicky18"}
];
factory.myGroups = [{
groupName: "Avangers",
members: ["vicky-1","vicky2","vicky3"]
}];
factory.getGroups = function (){
return factory.myGroups;
};
factory.getContacts = function (){
return factory.contacts;
};
factory.newcontact = [];
factory.newGroup = {};
factory.createMember = function (index) {
console.log(factory.contacts[index].email);
factory.newcontact.push(factory.contacts[index].email);
console.log("inside createmem()" + factory.newcontact);
};
factory.createGroup = function (groupName) {
factory.newGroup.groupName = groupName;
factory.newGroup.members = factory.newcontact;
factory.myGroups.push(factory.newGroup);
console.log(factory.newGroup);
factory.newcontact = [];
};
return factory;
});
the error i get is
Duplicates in a repeater are not allowed. Use 'track by' expression to
specify unique keys. Repeater: group in groups, Duplicate key:
object:019
this my code in jsfiddle
http://jsfiddle.net/vickyvignesh/E6NzM/

Related

How to get name and values from a javascript object into a new list?

I have this JavaScript object which is a collection of multiple lists(I believe). I need to create a select dropdown with the name being the name of the list, and a number of boxes with background color as per that name. Like this:
I am able to parse that object to get all the names of the colors, but I can't find a way to parse the names and the list of values it holds. This is how I tried :
var
YlGn3 = ['#f7fcb9', '#addd8e', '#31a354'],
YlGn4 = ['#ffffcc', '#c2e699', '#78c679', '#238443'],
YlGn5 = ['#ffffcc', '#c2e699', '#78c679', '#31a354', '#006837'];
var brewer = Object.freeze({
YlGn3: YlGn3,
YlGn4: YlGn4
});
var office = Object.freeze({
YlGn5: YlGn5
});
var colorschemes = {
brewer: brewer,
office: office
};
var scheme_list = [];
for (i in colorschemes){
for(j in colorschemes[i]){
console.log(j);
scheme_list.push(j);
}
}
I was thinking of creating a new object and append every color, along with the list of colors, so I can parse it again to create an option element with it. But, I am not able to figure out the best way to do that. Is this the correct approach ?
You use Object.values along with forEach multiple times.
Object.values(colorschemes).forEach(obj=>Object.entries(obj).forEach(([name,colors])=>{
const arr = [];
colors.forEach(color=>arr.push(color));
scheme_list.push([name, arr]);
}));
var
YlGn3 = ['#f7fcb9', '#addd8e', '#31a354'],
YlGn4 = ['#ffffcc', '#c2e699', '#78c679', '#238443'],
YlGn5 = ['#ffffcc', '#c2e699', '#78c679', '#31a354', '#006837'];
var brewer = Object.freeze({
YlGn3: YlGn3,
YlGn4: YlGn4
});
var office = Object.freeze({
YlGn5: YlGn5
});
var colorschemes = {
brewer: brewer,
office: office
};
var scheme_list = [];
Object.values(colorschemes).forEach(obj=>Object.entries(obj).forEach(([name,colors])=>{
const arr = [];
colors.forEach(color=>arr.push(color));
scheme_list.push([name, arr]);
}));
console.log(scheme_list);

Pouchdb join / link documents

I have pouchdb/couchbase data with equipment that has user assigned to them.
Equipment with _id and in the equipment doc there is a checkedOutBy with the user._id as the value. Within the employee object there is user.name. When I get the equipment objects how do I also get the user.name and display with the equipment.
I have searched and read about map/reduce that uses emit and do not grasp the idea. My code that i wrote from what i learned is:
by the way I am also using Angularjs.
field = "eq::"
this.getAllEquip = function(field){
function map(doc) {
if (doc.checkedOutBy !== undefined) {
emit(doc.checkedOutBy, {empName : doc.name});
}
}
var result = database.query(map, {include_docs: true,
attachments: true,
startkey: field,
endkey: field + '\uffff'})
.catch(function (err) {
//error stuff here
});
return result
};
I don't see where the two docs would get together. What am i missing? My result is empty.
The equipment json looks like:
{checkedOutBy: "us::10015", description: "3P Microsoft Surface w/stylus & power cord", equipId: "SUR1501", purchaseDate: "", rCost: 1000, id:"eq::10001"}
Emlpoyee json:
{"firstname":"Joe","gender":"male","lastname":"Blow","status":"active","title":"office","type":"userInfo","_id":"us::10015","_rev":"2-95e9f34784094104ad24bbf2894ae786"}
Thank you for your help.
Something like this should work, if I understood the question correctly:
//Sample Array of Objects with Equipment
var arr1=[{checkedout:"abc1",desc:"item1",id:1},
{checkedout:"abc2",desc:"item2",id:2},
{checkedout:"abc3",desc:"item3",id:3},
{checkedout:"abc1",desc:"item1",id:4},
{checkedout:"abc4",desc:"item3",id:5},
{checkedout:"abc6",desc:"item3",id:6}];
//Sample array of objects with Employee - the "id" in arr2 matches with "checkout" in arr1
var arr2=[{name:"john",id:"abc1"},
{name:"jack",id:"abc2"},
{name:"alice",id:"abc3"},
{name:"james",id:"abc4"}];
var result = []; //final result array
//loop through equipment array arr1
arr1.forEach(function(obj) {
var tempObj = obj;
var checkedout_id=obj.checkedout;
//do array.find which will return the first element in the array which satisfies the given function. This is absed on the assumption that that the id is unique for employee and there wont bwe multiple employees with same id (which is the "checkedout" field in equipment. If the employee is not found, it will return undefined.
var foundname = arr2.find(function(obj) {
if (obj.id == checkedout_id)
return obj.name
})
//Create the object to be inserted into the final array by adding a new key called "name", based on the result of above find function
if (foundname != undefined) {
tempObj.name=foundname.name
}
else {
tempObj.name = "Not found";
}
result.push(tempObj);
})
This is my Pouchdb solution, thank you Vijay for leading me to this solution.
First I get all my equipment. Then I use Vijay's idea to loop through the array and add the name to the object and build new array. I found there is a need to go into the .doc. part of the object as in obj.doc.checkedOutBy and tempObj.doc.name to get the job done.
$pouchDB.getAllDocs('eq::').then(function(udata){
var result = [];
//loop through equipment array
udata.rows.forEach(function(obj) {
var tempObj = obj;
var checkedout_id=obj.doc.checkedOutBy;
if (checkedout_id != undefined) {
$pouchDB.get(checkedout_id).then(function(emp){
return emp.firstname + " " + emp.lastname
}).then(function(name){
tempObj.doc.name = name;
});
}
result.push(tempObj);
})
in my service I have:
this.get = function(documentId) {
return database.get(documentId);
};
and:
this.getAllDocs = function(field){
return database.allDocs({
include_docs: true,
attachments: true,
startkey: field,
endkey: field + '\uffff'});
};

how to get dynamically created object inserted into another object

Good morning!
i have two dynamically created objects using form fields values. They are object literals which look like this:
var courses = {};
course['name'] = $('#course').val();
var students = {};
students['first'] = $('#first_name').val();
students['last'] = $('#last_name').val();
students['age'] = $('age').val();
I would like to insert them in a single object literal var person= {}
i need the two objects into one because I need to stringify it and send via ajax to my process page. Could you please help me?
You can populate an object as you are creating it:
var persons = {
courses: {
name: $('#course').val(),
},
students: {
name: $('#first_name').val(),
last: $('#last_name').val(),
age: $('#age').val(),
},
};
If you want to use the objects that you already have then you can do so:
var persons = {
courses: courses,
students: students,
};
You can create a object with the 2 objects like:
var data = {courses:courses,students:students};
or you can append one to the other
students['courses'] = courses;
And what's the problem?
Just place these objects into your object and then you can serialize it e.g. to JSON and send via ajax:
var person = {}
person.course = {};
person.student = {};
person.course['name'] = "Course 1";
person.student['first'] = "Vasya";
person.student['last'] = "Pupkin";
person.student['age'] = "26";
If you want multiple students, you should use arrays. Here we create an array with 3 objects, each represents a student:
var person = {}
person.course = {};
person.students = [{},{},{}];
person.course['name'] = "Course 1";
person.students[0]['first'] = "Vasya";
person.students[0]['last'] = "Pupkin";
person.students[0]['age'] = "26";
person.students[1]['first'] = "Petya";
person.students[1]['last'] = "Vasechkin";
person.students[1]['age'] = "30";
person.students[2]['first'] = "Vasiliy";
person.students[2]['last'] = "Alibabaevich";
person.students[2]['age'] = "40";
You can do the same thing with courses.
But in this case the name person for the object that contains all this data a bit confusing, because it contains multiple students. You should give meaningful names for your variables.

Backbone filter a collection using multiple attributes

I am new to backbone js. I am trying to create an application that displays certain data and allows users to filter them with certain attributes and narrow down results. My fetched data has three fields : Organisation name, Organisation type and Country. Users can apply filter on Organisation type and Country by selecting them from drop down list. The Organisation type and Country could be multiple. I used jQuery's select2 to allow users to select multiple organisation types and countries. The Organisation name is filtered on each keystroke on the input field. I managed to create a filter that filters the record based on all three attributes separately. Here's my collection along with my filter function:
var OrganisationCollection = Backbone.PageableCollection.extend({
model: Organisation,
state: {pageSize: 20},
mode: "client",
queryParams: {
currentPage: "current_page",
pageSize: "page_size"
},
filterBy: function(organisationName, organisationType, countryName){
var matchingModels;
var filterFunction = function(model) {
var check = (model.get('name').indexOf(organisationName)>-1);
return check;
}
collectionToFilter = this;
matchingModels = filteredCollection(collectionToFilter, filterFunction);
function filteredCollection(original, filterFn) {
var filtered;
// Instantiate new collection
filtered = new original.constructor();
// Remove events associated with original
filtered._callbacks = {};
filtered.filterItems = function(filter) {
var items;
items = original.filter(filter);
filtered._currentFilter = filterFn;
return filtered.reset(items);
};
// Refilter when original collection is modified
original.on('reset change destroy', function() {
return filtered.filterItems(filtered._currentFilter);
});
return filtered.filterItems(filterFn);
};
collectionToFilter = new OrganisationCollection(matchingModels);
return collectionToFilter;
}
});
Now, this filter function only filters the collection based on organisation name. If I were to filter my collection based on organisation type, my filterBy function would be:
filterBy: function(organisationName, organisationType, countryName){
var matchingModels;
var filterFunction = function(model) {
var check = typeof organisationType=='string' ? (model.get('type').indexOf(organisationType)>-1) : (_.indexOf(organisationType, model.get('type')) > -1);
return check;
}
collectionToFilter = this;
matchingModels = filteredCollection(collectionToFilter, filterFunction); // filterFunction would be same as above
collectionToFilter = new OrganisationCollection(matchingModels);
return collectionToFilter;
}
My filterBy country function would be similar to above.
Now my problem is that these three functions work fine separately. But I am unable to merge these three functions to narrow down the results. i.e. when a user filters with countries USA and Australia, types corporate and multilateral, only those organisations from countries USA and Australia having types corporate and multilateral are supposed to show. And again, among those results, if the user types 'A' in Organisation name input field, only those organisations from previous results starting with alphabet 'A' are supposed to show. I have no idea how to implement that.
Here's my function that triggers the filter:
$(document).ready(function(){
var country = $("#filter-country").val();
var countryName = country ? country : '';
var type = $("#filter-org-type").val();
var orgType = type ? type : '';
var orgName = '';
$("#filter").on('input',function(e){
var orgFilter = $('#filter').val();
orgName = orgFilter ? orgFilter : '';
orgCollection.trigger("filter-by-organisation",orgName, orgType, countryName);
});
// Users can select countries from select field #filter-country and types from select field #filter-org-type and click on button #apply-filters to trigger filter function
$(document).on('click', '#apply-filters', function(){
orgCollection.trigger("filter-by-organisation",orgName, orgType, countryName);
});
});
Please help me with this. Thanks
I might not have understood your problem very well, but you could simply do something like this:
var OrganisationCollection = Backbone.PageableCollection.extend({
model: Organisation,
filterBy: function(organisationName, organisationType, countryName) {
var organisationNameResults = this.filter(function(model) {
// your logic for filtering based on organisationName
});
var organisationTypenResults = _.filter(organisationNameResults, function(model) {
// your logic for filtering based on organisationType
});
var countryNameResults = _.filter(organisationTypenResults, function(model) {
// your logic for filtering based on countryName
});
this.reset(countryNameResults);
}
});
It can be refactored, this is just to give you an idea

Sorting grouped items in listview

I need to sort individual items in groups.
The Listview api lets me to create sorted groups or sort whole list.
I need to sort item in the respective groups.
Is it possible?
I was struggling with the same issue and neither found a useful example, nor a hint. Then I started to combine SortedListProjection and GroupedSortedListProjection, and by that, finally made it work.
My use case was to have groups in alphabetical, ascending order, but within a group, have the items ordered by a timestamp, descending.
Here is how I set it up in the JavaScript file:
var list = new WinJS.Binding.List(); // list gets populated later in the code
var sortedList = list.createSorted(compareItems);
var groupedList = list.createGrouped(getGroupKey, getGroupData, compareGroups);
WinJS.Namespace.define("my.stuff", {
sortedList: sortedList,
groupedList: groupedList
});
The important thing was to keep the item sorting in sync with the grouping. Therefore the item sorting function is calling grouping functions.
Below are all four functions used for sorting and grouping:
compareItems = function (leftItem, rightItem) {
let leftKey = getGroupKey(leftItem);
let rightKey = getGroupKey(rightItem);
let compare = compareGroups(leftKey, rightKey);
if (compare == 0) { // if keys are equal compare timestamps
return leftItem.timestamp < rightItem.timestamp ? 1
: leftItem.timestamp > rightItem.timestamp ? -1 : 0;
}
return compare;
};
getGroupKey = function (item) {
return item.name + item.category;
};
getGroupData = function (item) {
return {
name: item.name + " (" + item.category + ")"
};
};
compareGroups = function (leftKey, rightKey) {
return leftKey.toUpperCase().localeCompare(rightKey);
};
Finally, the combined declaration of both lists for the ListView:
<div id="dataDeliveriesList" class="hidden"
data-win-control="WinJS.UI.ListView"
data-win-options="{
itemDataSource: my.stuff.sortedList.dataSource,
itemTemplate: select('#itemTemplate'),
groupDataSource: my.stuff.groupedList.groups.dataSource,
groupHeaderTemplate: select('#groupHeaderTemplate'),
layout: {
type: WinJS.UI.ListLayout
}
}">
</div>
It's possible. ObservableCollection doesn't provide a sorting option, and therefore you'll have to create a new collection that's sorted on a selected property. See sample code below. For other sorting options, read the blog post here and another stackoverflow thread.
// TODO: Create an appropriate data model for your problem domain to replace the sample data
var group = SampleDataSource.GetGroup((String)navigationParameter);
this.DefaultViewModel["Group"] = group;
//this.DefaultViewModel["Items"] = group.Items;
// Sort items by creating a new collection
ObservableCollection<SampleDataItem> grpSorted = new ObservableCollection<SampleDataItem>(
group.Items.OrderBy(grp => grp.Title));
this.DefaultViewModel["Items"] = grpSorted;

Categories

Resources