How to get the key of a firebaseArray object - arrays

I am trying to get the key for a returned firebaseArray record but am having no luck.
I have aservice that runs the following to return a store
getStore: function(uid, id){
var ref = firebase.database().ref('u/'+uid+'/stores/'+id+'/i/');
// to take an action after the data loads, use the $loaded() promise
return $firebaseArray(ref);
}
I use the following to get eeach record by calling the service
for(var i = 0; i < $scope.storesList.length; i++){
var storeInfo = Stores.getStore($rootScope.user['uid'], $scope.storesList[i]['$id']);
storeInfo.$loaded().then(function(data){
$scope.stores.push(data);
console.log($scope.stores);
});
}
In my html I can access various properties within the array
<li ng-repeat="store in stores">
<span class="store-address">{{store.$getRecord('name').$value}}</span>
<span class="store-address">{{store.$getRecord('address1').$value}}</span>
</li>
But I cannot seem to get the id for each store record from within the ng-repeat

To get the id simply call the $id on the item.
<li ng-repeat="store in stores">
<span class="store-address">{{store.$getRecord('name').$value}}</span>
<span class="store-address">{{store.$getRecord('address1').$value}}</span>
<span class="store-address">{{store.$id}}</span>
</li>
See: https://github.com/firebase/angularfire/blob/master/docs/reference.md#firebasearray

Instead of getting yourself complicated, try this simple code!
var ref = new Firebase(url);
ref.once("value", function(list) {
var subData = list.val();
var subDataKey = list.key();
console.log(subDataKey);
This must help you!

I solved this by switch from firebaseArray to firebaseObject which contains an $id parameter

Related

Synchronous Filters with AngularFire

I'm working with AngularFire and I'm trying to make a filter with a query to my firebase database, but when I want to return the result, it doesn't execute it.
My html:
<ul>
<li ng-repeat="(office, job) in user.sucursales"><span>#{{office | searchOffice:company.$id }} </span> - #{{ job }} </li>
</ul>
My filter:
app.filter('searchOffice', ['$firebaseObject', function($firebaseObject){
return function(office, company){
var ref_office = firebase.database().ref('sucursales').child(company).child(office);
var office2 = $firebaseObject(ref_office);
var office_name = 'hello';
office2.$loaded().then(function(x){
var office_name = x.nombre
console.log(office_name);
return office_name;
})
}
}])
When I print the console.log(office_name) it gives me a correct result, the office's name, but when I want to return that result, is like don't get that part of the code. What can I am doing wrong?
Hope can help me. Thank you.

dynamically change options in dropdown list in angular js

i tried to create dynamically changing dropdown list in angularJS
angulars.js
var option1Options = ["Class","Category","Option","Question","Group"];
var option2Options = [["Group","ProductModel"],
["Class","ProductModel"],
["Class","Group","ProductModel"],
["Group","ProductModel"],
["ProductModel"]];
$scope.myCtrl= function()
{
$scope.options1 = option1Options;
$scope.options2 = [];
$scope.getOptions2 = function(){
var key = $scope.options1.indexOf($scope.child);
$scope.options2 = option2Options[2];
};
}
page.html
<div id="CreateChild" ng-controller="myCtrl">
<select ng-model="child" ng-options="option for option in options1" ng-change="getOptions2()">
</select>
<select ng-model="parent" ng-options="option for option in options2">
</select>
</div>
in angulars.js i was unable to get the index of first dropdown list array. the value of key is assigned as -1 and the option2 is assigned as undefined.
can any one help me with this
I did a small workaround for this requirement, though it is not a straight answer, I believe this would help you...
Add this to your controller...
$scope.getOptions1Idx = function(){
var mySelectedOption = $scope.child;
var i = 0;
for(i=0;i< option1Options.length;i++){
if(option1Options[i]==mySelectedOption){
break;
}
}
return i;
}
and change your getOptions2 function as follows
$scope.getOptions2 = function(){
$scope.options2 = option2Options[getOptions1Idx()];
};
This can be done in much better fashion by avoiding for loop provided if you choose to change your array structure with predefined index some thing like var option1Options = [{id:0,option:"Class"},{id:1,option:"Category"},{id:2,option:"Option"},{id:3,option:"Question","Group"}];
Had a very similar problem with this. In terms of styling I found my way around it by creating a list instead of a select option
<div class='btn-group'>
<button class='form-control col-md-3' data-toggle='dropdown'>
{{value}} <span class='caret'></span>
</button>
<ul class='dropdown-menu'>
<li ng-repeat='type in callType' class='col-md-3'>
<a href='#' ng-click='select(type)'>{{type.name}}</a>
</li>
</ul>
</div>
Then the controller is used to take in the objects, call a method to change each object and then set a default for the drop down list. You can see it at the link below.
http://plnkr.co/edit/nwXmMif8vjj92pQmalb2

updating a single value in localstorage

So i've got this piece of code to update the date and time a person leaves in localstorage
$scope.visitorout = function(){
var dateout1 = new Date();
var signout = JSON.parse(localStorage["allVisitors"]);
for(var i=0;i<signout.length;i++)
if (signout[i].id===signout[i].id) signout[i].dateout = dateout1;
localStorage["allVisitors"] = JSON.stringify(signout);
};
but whenever i call the function, it changes all the values of dateout for every single thing in local storage but i only want it to change just one
I have modified the code to this:
$scope.visitorOut = function(id){
var allVisitors = JSON.parse(localStorage["allVisitors"]);
var visitor;
for(var i=0; i<allVisitors.length; i++){
visitor = allVisitors[i];
if (allVisitors[i].id === visitor.id) {
visitor.dateout = new Date();
console.log(visitor.id)
break;
}
}
localStorage["allVisitors"] = JSON.stringify(allVisitors);
};
It updates the 'dateout' but for just the same item in localstorage and the console.log displays the same id each time...
<div class="list">
<a class="item item-icon-left item-icon-right" ng-repeat="visit in visits | orderBy: '-date'" ng-click="visitorOut(id); closesignout()" ng-hide="visit.hide">
<i class="icon ion-person"></i>
{{visit.fname}} {{visit.lname}}
<i class="icon ion-log-out" ng-click="hideMe(visit)"></i>
This code looks like a bug. You are comparing an object to itself (which will always be true):
if (signout[i].id===signout[i].id)
This function needs to know which visitor to update. Wherever you're calling this function, you need to pass in at least the userId (if not the full user object) something like: $scope.visitorOut(user.id) or from html: <myElement ng-click="visitorOut(user.id)" />
$scope.visitorOut = function(userId){
var allVisitors = JSON.parse(localStorage["allVisitors"]);
var visitor;
for(var i=0; i<allVisitors.length; i++){
visitor = allVisitors[i];
if (visitor.id === userId) {
visitor.dateout = Date.now();
break;
}
}
localStorage["allVisitors"] = JSON.stringify(signout);
};
Note that I've used Date.now() here instead of new Date(). It's much easier to work with timestamps than Dates if you're going to stringify it. A timestamp can be converted to a Date like this:
var myDate = new Date(visitor.dateOut);
But if you want to convert a stringified date back to a Date object... it gets complicated (click).
I also changed the variable names a bit. Camelcase is a useful naming convention that aides readability, and from reading the rest of the code the signout variable seems to actually be an array of visitor objects, not an array of signouts, so I renamed that too.

How to get a single item from a GoInstant collection?

How do you get a single item from a GoInstant GoAngular collection? I am trying to create a typical show or edit screen for a single task, but I cannot get any of the task's data to appear.
Here is my AngularJS controller:
.controller('TaskCtrl', function($scope, $stateParams, $goKey) {
$scope.tasks = $goKey('tasks').$sync();
$scope.tasks.$on('ready', function() {
$scope.task = $scope.tasks.$key($stateParams.taskId);
//$scope.task = $scope.tasks.$key('id-146b1c09a84-000-0'); //I tried this too
});
});
And here is the corresponding AngularJS template:
<div class="card">
<ul class="table-view">
<li class="table-view-cell"><h4>{{ task.name }}</h4></li>
</ul>
</div>
Nothing is rendered with {{ task.name }} or by referencing any of the task's properties. Any help will be greatly appreciated.
You might handle these tasks: (a) retrieving a single item from a collection, and (b) responding to a users direction to change application state differently.
Keep in mind, that a GoAngular model (returned by $sync()) is an object, which in the case of a collection of todos might look something like this:
{
"id-146ce1c6c9e-000-0": { "description": "Destroy the Death Start" },
"id-146ce1c6c9e-000-0": { "description": "Defeat the Emperor" }
}
It will of course, have a number of methods too, those can be easily stripped using the $omit method.
If we wanted to retrieve a single item from a collection that had already been synced, we might do it like this (plunkr):
$scope.todos.$sync();
$scope.todos.$on('ready', function() {
var firstKey = (function (obj) {
for (var firstKey in obj) return firstKey;
})($scope.todos.$omit());
$scope.firstTodo = $scope.todos[firstKey].description;
});
In this example, we synchronize the collection, and once it's ready retrieve the key for the first item in the collection, and assign a reference to that item to $scope.firstTodo.
If we are responding to a users input, we'll need the ID to be passed from the view based on a user's interaction, back to the controller. First we'll update our view:
<li ng-repeat="(id, todo) in todos">
{{ todo.description }}
</li>
Now we know which todo the user want's us to modify, we describe that behavior in our controller:
$scope.todos.$sync();
$scope.whichTask = function(todoId) {
console.log('this one:', $scope.todos[todoId]);
// Remove for fun
$scope.todos.$key(todoId).$remove();
}
Here's a working example: plunkr. Hope this helps :)

AngularJs delete record on nested grouped rows

I'm trying to build a simple page to group record and then add a button to eliminate some records.
The problem is that the record eliminated that has the same name is deleted from the wrong grouped list. And also if a list have no grouped records should disappear, and instead is always there.
Fiddle: http://jsfiddle.net/Tropicalista/qyb6N/15/
// create a deferred object to be resolved later
var teamsDeferred = $q.defer();
// return a promise. The promise says, "I promise that I'll give you your
// data as soon as I have it (which is when I am resolved)".
$scope.teams = teamsDeferred.promise;
// create a list of unique teams
var uniqueTeams = unique($scope.players, 'team');
// resolve the deferred object with the unique teams
// this will trigger an update on the view
teamsDeferred.resolve(uniqueTeams);
// function that takes an array of objects
// and returns an array of unique valued in the object
// array for a given key.
// this really belongs in a service, not the global window scope
function unique(data, key) {
var result = [];
for (var i = 0; i < data.length; i++) {
var value = data[i][key];
if (result.indexOf(value) == -1) {
result.push(value);
}
}
console.log(result)
console.log(Math.ceil(result.length / 10))
$scope.noOfPages = Math.ceil(result.length / 10);
return result;
}
$scope.currentPage = 1;
$scope.pageSize = 5;
$scope.maxSize = 2;
$scope.deleteItem = function(item){
//code to delete here
var index=$scope.players.indexOf(item)
$scope.players.splice(index,1);
};
Here is a sample of something expanding on the tip from SpykeBytes
<div ng-repeat="location in journey.locations">
<div id="location_div_{{ $index }}">
<label class="journey-label">Location name</label>
<input class="journey-input" id="location_{{ $index }}" type="text" ng-model="location.location_name" />
<button ng-show="editable" tabindex="-1" class="journey-button remove" ng-click="removeItem(journey.locations, $index)">
Remove location
</button>
Then in my controller I set up an action that takes deletes the individual item
$scope.removeItem = function(itemArray, index) {
return itemArray.splice(index, 1);
};
To hide the group when nothing is listed, you need to get the filtered list and then use ng-show to drive the display. This is a bit tricky:
<div ng-show="currentList.length>0" ng-repeat="team in teams| startFrom:(currentPage - 1)*pageSize | limitTo:pageSize | filter:searchInput"> <b>{{team}}</b>
<li ng-repeat="player in (currentList = (players | filter: {team: team}))">{{player.name}}
<button class="btn btn-small" type="button" ng-click="deleteItem(player)">Delete</button>
</li>
</div>
However I am not seeing the problem you said about removing from wrong group. Can you let me know how to reproduce it?
Index won't help you here because the {{$index}} that ng-repeat provides is within the groupings. That is, each grouping restarts the $index variable. You are going to need a unique identifier for each record though. Without that there is no way to be sure that the record you want to remove is the right one.
As far as the groupings, you can recreate the model whenever you delete something. This wouldn't work with the sample data in the Fiddle, but it works when you're dealing with a real datasource.
You can instead pass the index of the object if it is within ng-repeat.

Resources