Synchronous Filters with AngularFire - angularjs

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.

Related

How to get the key of a firebaseArray object

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

Retrieving and rendering data from Firebase in Angular

I am using Angular to add data (Users and their Orders) to Firebase.
Below is the DB structure in Firebase.
Firebase DB Structure
Below is the code I am using to RETRIEVE all the Orders for a particular User from Firebase.
var orddataref = fbref.child("profile").child($scope.cart.userkey).child("orders");
orddataref.on("child_added", function(snap) {
ordersRef.child(snap.key()).once("value", function(snapshot) {
$scope.odata = snapshot.val();
$scope.apply();
});
});
Below is the code I am using to RENDER in my HTML.
<div ng-repeat="order in odata">
<div> Order Address : {{order.address}}</div>
<div> Deliverynotes : {{order.deliverynotes}}</div>
<div> Total Amount : {{order.totalamount}}</div>
<ion-item class ="item" ng-repeat="item in order.items">
<div> Item SKU : {{item.sku}}</div>
<div> Price : {{item.price}}</div>
<div> Quantity : {{item.quantity}}</div>
</ion-item>
</div>
It is getting only current item back and not all the orders (including previous orders).
Can anyone suggest where I am going wrong? Any help is appreciated very much.
Edited after Frank's suggestion
Frank, I put a breakpoint on the line $scope.odata = snapshot.val(); It is just having the current order as below.
{"address":"Auckland, New Zealand","deliverynotes":"At door","items":[{"price":3,"quantity":2,"sku":"1002"},{"price":6.5,"quantity":3,"sku":"2002"}],"totalamount":25.5}
So I put a logger after it.
console.log("displayOrders - orderdata :===", $scope.odata);
Below is a screengrab of chrome console where I see all the orders.
All Orders
How do I get all these orders into $scope.odata?
Just cracked it.
Below is the correct code for getting all orders for a particular user.
Please refer to the Database structure in the question if you need to.
$scope.odata = {};
$scope.tempdata =[];
var fbref = new Firebase("https://xxxxxxx.firebaseio.com/");
var ordersRef = fbref.child("orders");
var orddataref = fbref.child("profile").child($scope.cart.userkey).child("orders");
orddataref.on("child_added", function(snap) {
ordersRef.child(snap.key()).once("value", function(snapshot){
$scope.tempdata.push(JSON.parse(JSON.stringify(snapshot.val())));
});
});
$scope.odata = $scope.tempdata;
Since I am a newbie, if anyone has a better solution, please suggest.
#Frank, thank you for pointing to the right path.

How to search on the displayed data and not the backing data using Angular

I am using ng-repeat to create a table of data:
<div class="divTable" ng-repeat="expense in exp.expenses | filter:exp.query">
<div>{{expense.amount | ldCurrency : true}}</div>
...
</div>
A couple of the cells that I am creating are being modified through an Angular filter. In the example above, I am changing the integer to a currency. So the original 4 is changed to $4.00. When I filter the entire list with my exp.query, it does not modify the exp.query search term through the ldCurrency.
The means that if I search on $4, it will not find it, because the backing data is 4, even though $4 is on the page.
I know this is confusing, with the two types of filters that I am talking about here.
How can I search on the data that is being shown on the page and not on the backing data?
You have to create you own filter. What you want to do to is a bad idea, because you are melding the view layer and the model layer.
A example of a filter.
The html:
<input ng-model="query" ng-trim="true">
<span>Finding: </span><span>{{ query }}</span>
<div ng-repeat="product in products | productsFilter: query">
<strong>{{ $index }}</strong>
<span>{{ product.name }}</span>
<span>{{ product.price | currency: '$'}}</span>
</div>
The custom filter:
.filter('productsFilter', [function () {
// Private function: It removes the dollar sign.
var clearQuery = function (dirtyQuery) {
var index = dirtyQuery.indexOf('$');
if (index === -1)
return dirtyQuery;
return dirtyQuery.substr(index+1, dirtyQuery.length-index)
};
// The Custom filter
return function (products, query) {
if (query === '') return products;
var newProducts = [];
angular.forEach(products, function (product) {
var cleanQuery = clearQuery(query);
var strProductPrice = '' + product.price;
var index = strProductPrice.indexOf(cleanQuery);
if (index !== -1) {
newProducts.push(product);
}
});
return newProducts;
};
}]);
The key is in the angular.forEach. There I decide if the product will belong to the new filtered collection. Here you can do the match you want.
You can find the complete example in full plucker example and see a lot of filters in the a8m's angular-filter

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

AngularJS: Filter Too Lax - incorrect display

I have an object of attachments returned from a SharePoint custom list with each named as ProjectID | RequestID | TaskID | Filename.
I am trying to filter according to my needs (only 1 ID will be present with the filename and the rest are usually 0 unless there is sharing going on) but when I filter where PID (Project ID) == 1, it displays where PID is 1 AND 17. How do I tighten up the filter to match EXACT?
Here is a plunkr.
Here is my HTML:
<body ng-controller="MainCtrl">
<h3>All Attachments:</h3>
<ul>
<li ng-repeat="att in attachments">{{att.Title}}</li>
</ul>
<hr />
<h3>Attachments for Project #1</h3>
<ul>
<li ng-repeat="pat in fstProj = (attachments | filter:{PID:'1'})">{{pat.Title}}</li>
</ul>
</body>
and here is the Javascript:
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope, catFactory) {
$scope.attachments = catFactory.getAttachments();
});
The filter filter uses string-matching. sinc eyou want to compare exact numbers, you can filter by a user-defined function:
<li ng-repeat="pat in attachments | filter:byPID">{{pat.Title}}</li>
$scope.byPID = function (item) {
return item.PID === 1;
}
See, also, this short demo.
UPDATE:
Of course, if you are willing to use a more recent version of Angular (not from the 1.0.* branch) (which you absolutely should), there is a third paramter to be passed to filter, in order to do strict matching (instead of substring):
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js" ...>
...
<li ng-repeat="pat in attachments | filter:{PID:1}:true">{{pat.Title}}</li>
In this case, nothing else needs to be changed.
See, also, this other demo.

Resources