google-realtime-api - how to access all the objects in a file - google-drive-realtime-api

So I am trying to add multiple objects to my google-realtime-api app. For example, I've got something like this:
function onFileInitialize (model) {
var collaborativeList = model.createList();
collaborativeList.pushAll(['Cat', 'Dog', 'Sheep']);
model.getRoot().set('demo_list', collaborativeList);
var collaborativeList2 = model.createList();
collaborativeList2.pushAll(['1', '2', '3']);
model.getRoot().set('demo_list2', collaborativeList2);
My question is how can I access them all at the same time? So it would be possible to render them and add event-listeners to them without having to do it separately by first getting 'demo_list' and then 'demo_list2' and repeating a lot of code.
Is it possible with realtime to do something like:
for (var i=0...) { doc.getModel().getRoot().get(i); };
?

The root is a CollaborativeMap, so you can use getKeys or getValues to iterate through all the items.

Related

Best approach in moving data from one array to a new array in angular ts

.subscribe((dataChart) => {
// console.log(dataChart)
var forxaxis = []
var cd = [dataChart]
// console.log(cd)
cd.forEach(element => {
forxaxis.push(element.strRequestDate)
console.log(forxaxis)
});
},
Im trying to move my data in the first array into a new array so that I can use it with chart.js. but it didnt work.
dataChart contain 2 column of data. i insert dataChart into an array called cd. then i tried to push one of the column from dataChart which is called strRequestDate into a new array called forxaxis but it just didnt work as per expected. the result is as shown in the image attached.
this is how the data look like. it was called by using sharepoint API
error and the data
You can use array.map property here, so you don't need to push data manually from one array to another
I have taken sample data in dataChart array for demonstration purpose only.
let dataChart = [{strRequestId: 1, strRequestDate: 'ABC'}, {strRequestId: 1, strRequestDate: 'PQR'}];
let forxaxis = dataChart.map(x => x.strRequestDate);
console.log(forxaxis);
Demo
Output:

Mutating array within an array (Polymer iron-list)

I currently have an iron-list within another iron-list. The parent's data comes from a firebase-query element, and the child's data is computed from each parent item. The db structure and code looks a bit like this:
DB: [
category1: [
itemId1: {
price: 10,
title: "title"
}
]
]
<iron-list id="categoryList" items="{{categories}}" multi-selection as="category">
<template>
<div class="category-holder">
<iron-list id="{{category.$key}}" items="{{_removeExtraIndex(category)}}" as="item" selection-enabled multi-selection selected-items="{{selectedItems}}" grid>
<template>
<div class$="{{_computeItemClass(selected)}}">
<p>[[item.title]]</p>
<p>[[item.price]]</p>
</div>
</template>
</iron-list>
</div>
</template>
</iron-list>
After selecting any number of items, the user can tap on a fab to batch edit the price. This is where I'm having issues. I can't figure out how to access the correct child iron-list in order to call list.set...I'm currently trying the following very nasty method:
var categories = this.$.categoryList;
var categoryItems = categories.items;
(this.selectedItems).forEach(function(item) {
var index = item.itemId;
categoryItems.forEach(function(itemList, categoryIndex) {
if (itemList[index]) {
categories.set('item.' + categoryIndex + '.price', 10);
}
}, this);
}, this);
I'm iterating over the selected items in order to extract the item index and then iterating over the parent iron-list data (categoryItems) in order to check if the given item exists in that subset of data. If so, then I use the category index and attempt to call set on the parent iron-list using the given path to access the actual item I want to edit. As expected, this fails. Hopefully I've made myself clear enough, any help would be appreciated!
EDIT #1:
After much experimenting, I finally figured out how to correctly mutate the child iron-list:
(this.selectedItems).forEach(function(item) {
var list = this.$.categoryList.querySelector('#' + item.category);
var index = list.items.indexOf(item);
list.set(["items", index, "price"], 30);
}, this);
A couple of things worth noting. I'm using querySelector instead of the recommended this.$$(selector) because I keep running into a "function DNE" error. But now I have another problem...after calling the function, the value gets updated correctly but I get the following error:
Uncaught TypeError: inst.dispatchEvent is not a function
Here's a picture of the full error message:
I see the light, hopefully someone can help me out!
OK, I'll take a shot at this. I think the following happens, and I guess this based on how dom-repeat works:
var categories = this.$.categoryList;
var categoryItems = categories.items;
You take the variable that the iron-list is based on, but setting one array to another just creates a reference in javascript. As soon as you update categoryItems, you also update this.$.categoryList.items. When you later sets the new value, iron-list will do a dirty check and compare all subproperties, and because they are equal (because ... reference), the iron-list wont update the dom.
What you should do is to make sure it's a totally new copy and the way of doing that is to use JSON.parse(JSON.stringify(myArray)).
Further on, one major flaw I see in your code is that you're using querySelector to select an element, and then manipulate that. What you should do is to use this.categories and only that variable.
So your method should look something like:
// Get a freshly new array to manipulate
var category = JSON.parse(JSON.stringify(this.categories);
// Loop through it
category.forEach(category) {
// update your categoryList variable
}
// Update the iron list by notifying Polymer that categories has changed.
this.set('categories', category);

How to prepare arrays for insertion into Firebase database?

I have a question about adding arrays to Firebase using AngularFire. Let's start with a quick example. What I tend to do when my users on the front end create a list is something like this:
angular.module("app", ["firebase"])
.controller("createListCtrl", function($scope, $firebaseArray) {
console.log("controller loaded");
$scope.newList = [];
$scope.addItemToList = function(itemlist) {
console.log(itemlist);
$scope.newList.push({
"item": itemlist,
"done": false
});
}
$scope.sendToDb = function() {
var ref = new Firebase("https://xxxxxx.firebaseio.com");
var list = $firebaseArray(ref);
list.$add({
"list": $scope.newList
}).then(function(ref) {
var id = ref.key();
console.log("added record with id " + id);
console.log(list.$indexFor(id)); // returns location in the array
})
}
Ok all nice and dandy and it all works great but I then I read this article:
https://www.firebase.com/blog/2014-04-28-best-practices-arrays-in-firebase.html
And I heard more people say to avoid arrays and I see the problem with array in Firebase, but what is the alternative, the article says this structure:
{foo: {counter: 1}, bar: {counter: 1}, baz: {counter: 1}};
Is that really a better structure? I think it gets messy and I don't even know how I would achieve this structure starting with something like this:$scope.newList = {};. Is it really a problem doing it with an array. Are arrays really evil in Firebase? Thanks in advance for an explanation or a better alternative.
edit
This is how the list is stored in Firebase, which does not seem very good:
---uniqueID
---list
---0
---done:false
---item:"item1"
---1
---done:false
---item:"item2"
---2
---done:false
---item:"item3"
The $firebaseArray class, which you're already using, provides a mapping between Firebase's ordered collections (which use push ids for their keys) and AngularJS's array (which use regular arrays).
So in your controller's constructor instead of creating a local array for itemList, create a two-way synchronized $firebaseArray:
$scope.newList = $firebaseArray(new Firebase("https://xxxxxx.firebaseio.com"));
The blog post you're referring to served as the basis for quite a few changes to AngularFire since then. I highly recommend that you work through the AngularFire development guide. It will take at most a few hours and will answer many more questions than just this one (which is covered in the section on synchronized arrays).
Update
Thanks for the update. I now get what you're trying to do. So you initially want to keep the list of items client-side only, and then all at once save it to Firebase.
In that case, I'd write sendToDb like this:
$scope.sendToDb = function () {
var ref = new Firebase("https://xxxxxx.firebaseio.com");
var listRef = ref.push();
$scope.newList.forEach(function(item) {
var itemRef = listRef.push({ item: item.item, done: item.done });
console.log('Added item with key: '+itemRef.key());
});
}
This uses the regular Firebase JavaScript SDK. But since AngularFire is built on top of that, they will co-exist without problems.
So instead of pushing the array in one go, I simply loop over the items in it and push each of them.
Working fiddle here: https://jsfiddle.net/frankvanpuffelen/vnh5dbwq/11/

BackboneJS - get specific value from Model using .max

So I have this:
var competitionModel = new Competition.CompetitionModel();
competitionModel.contest_id = this.contest_id;
this.insertView('.comp', new Competition.View({model: competitionModel}));
competitionModel.fetch();
So far so good, the Model and its (selected) values are getting display in the <div class="comp">.
Now I want to get a specific value from the same Model, in this case profile_image and it has to be the MAX value from the model. I read something about .max()-method but I dont know how to use it
I have this structure:
<div class="image"></div>
<div class="comp"></div>
1) is it possible? 2) can I use the same methods? like this.insertView('.image', blablab)
So, could anyone help me out?
Ok, judging by your comment the property is an array of things.
You cannot use the backbone max (which only applies to collections) but you can use the underscore max (they are the same thing, in the end, the former is a wrapper for the latter but let's not go into the details). You can see the collection .max() in action here.
You should be able to do something like this:
var max = _.max(competitionModel.get("property"));
Eventually you can pass a function to transform values:
var max = _.max(competitionModel.get("property"), function (element) {
// element is a single item in the list, return a number here.
});
Alternatively you can also use the underscore wrapper like this:
var max = _(competitionModel.get("property")).max(function (e) { ... });
More on max() can be found in the Underscore Docs.

backbone routes - ordering and filtering

In my Backbone app, on my collection I have numerous sorting methods, when rendering the views based on the collection I am currently using a global var set via the route (I do it with a global as other actions add to the collection and I want the last ordering to be used). For example
routes : {
"" : "index",
'/ordering/:order' : 'ordering'
},
ordering : function(theorder) {
ordering = theorder;
listView.render();
},
then in my view
if (typeof ordering === 'undefined') {
d = this.collection.ordered();
}
else if(ordering == 'owners') {
d = this.collection.owners();
}
_.each(d, function(model){
model.set({request : self.model.toJSON()});
var view = new TB_BB.OfferItemView({model : model});
els.push(view.render().el);
});
Where ordered and owners are the 2 ordering methods.
So my first question is, based on routes could someone advice a better way of implementing above? This view gets rendered in multiple places hence me using a global rather than passing a ordered var to the method?
Second question is - I would like to also add some filtering, so lets say I want to sort by 'price' but also do some filtering (lets say by multiple categories id). How could I add a flexible 'route' to deal with filtering.
I guess I could do
routes : {
"" : "index",
'/ordering/:order/:filter1/:filter2' : 'ordering'
},
So the filter1 and filter2 would be the subsequent filtering, but if the filters could be 0 or 100 this will not work. Could anyone offer a solution?
Well, first you should be using Backbone's built-in ability to auto-sort collections. You can take advantage of this by defining a comparator function on your collection. This gives you all kinds of wins right out of the box — for example, the collection will re-sort itself every time you add or remove something from it, based on your comparator. If you want to define multiple sort functions, just define them all as functions and then update comparator when you need to. Then you can ditch that ugly global var.
For your second question, I'm not totally sure what you mean by "if the filters could be 0 or 100 this will not work." If you mean that you'll run into trouble if you don't specifiy all of the filters, then that's true. But you can use a wildcard to fix that. Here's what that might look like:
// your routes look like this:
routes : {
'/ordering/:order/filters/*filters' : 'ordering' // your routes will look like: /ordering/price/filters/filter_one/filter_two/filter_three
},
ordering: function (order, filters) {
filters = filters.split('/'); // creates an array of filters: ['filter_one', 'filter_two', 'filter_three']
listView.render(filters); // pass your filters to the view
}
// listView.render() looks like this:
render: function(filters) {
collection = this.collection;
_.each(filters, function (filter) {
collection = collection.filter(function () {
// your actual filtering code based on what the filter is
});
});
}

Resources