I am trying to display exactly how many of an array variable I have, not just the items in the array, but one of the 'tags' assigned to it.
$scope.products = [
{
too: 'xxx-xxx-xxx',
foo: 'xxx',
bar: 'xxx-xxx',
}
}
];
When I try to list the length of one of the 'tags' for example "Foo".
Using {{foo.length}} will not work.
I would want my HTML to look something like this:
Menu 1 (1) <--- With this being the "foo" value.
*The foo value will change based on the amount of 'items' i have in my array, so if I had an array like this:
$scope.products = [
{
too: 'xxx-xxx-xxx',
foo: 'xxx',
bar: 'xxx-xxx',
}
{
too: 'yyy-yyy-yyy',
foo: 'yyy',
bar: 'yyy-yyy',
}
}
];
the HTML would reflect that I now have '2' values of 'foo', so it would say
Menu 1 (2), and so on and so forth.. How can I accomplish this?
You can write a javascript function and just call it. (updated to only count unique foos)
$scope.countUniqueFoos = function () {
var uniqueFoos = []; //you could also keep this as a $scope variable if needed
$scope.products.forEach( function (product) {
if (product.hasOwnProperty('foo') && uniqueFoos.indexOf(product.foo) == -1) {
uniqueFoos.push(product.foo);
}
});
return uniqueFoos.length;
};
And in the HTML:
<div>NumFoos: {{countUniqueFoos()}}</div>
Related
In my state I have an object called foodLog which holds all entries a user enters with one of the keys being foodSelectedKey and I'm trying to return all entries that have a matching value from that key with a different array called foodFilter.
However, this doesn't work and errors out saying foodLog.filter() isn't a function - I've looked this up and it's because it's an Object (I think). Any help would be greatly appreciated!
state = {
// log food is for the logged entries
foodLog: {},
// used for when filtering food entries
foodFilter: [],
};
findMatches = () => {
let foodLog = this.state.foodLog;
let foodFilter = this.state.foodFilter;
let matched = foodLog.filter((item) => {
return foodLog.foodsSelectedKey.map((food) => {
return foodFilter.includes(food);
});
});
};
I guess the reason behind the error Is not a function is that the object can not be looped. By that it means you can not iterate an object with differend variables inside, if it has no index to be iterated like an array. The same goes for map(), find() and similar functions which MUST be run with arrays - not objects.
As far as I understand you have an object named foodLog which has an array named foodsSelectedKey. We need to find intersected elements out of foodFilter with the array. This is what I came up with:
state = {
// log food is for the logged entries
foodLog: {
foodsSelectedKey: [
{ id: 1, name: "chicken" },
{ id: 2, name: "mashroom" }
]
},
// used for when filtering food entries
foodFilter: [
{ id: 1, name: "chicken" },
{ id: 2, name: "orange" }
]
};
findMatches = () => {
let foodLog = this.state.foodLog;
let foodFilter = this.state.foodFilter;
let matched = foodLog.foodsSelectedKey.filter((key) =>
{
for (let i=0; i<foodFilter.length;i++){
if(foodFilter[i].name===key.name)
return true
}
return false;
}
);
return matched;
};
The Output is filtered array, in this case, of one element only:
[{
id: 1
name: "chicken"
}]
In order to check the output - run console.log(findMatches()). Here is the CodeSandbox of the solution. (check console at right bottom)
I want to find a value inside an array that is already inside an array.
To give an example of my array:
[
{
ConcessionId: 1,
ConcessionName: "Coyotes",
KnownAs: [
{
TeamId: 1,
Name: "Arizona Coyotes",
},
{
TeamId: 2,
Name: "Phoenix Coyotes",
}
]
},
{
ConcessionId: 2,
ConcessionName: "Devils",
KnownAs: [
{
TeamId: 3,
Name: "Colorado Rockies",
},
{
TeamId: 4,
Name: "New-Jersey Devils",
}
]
}
]
What I want is when Icall my function it returns me the team name.
For example, I the parameter value is 3, I want Colorado Rockies as a name:
public getInfo(_TeamID) {
const concession: ConcessionInfo[] = this.concessionList$.filter(function (x) {
x.KnownAs.filter( (y)=> {
y.TeamId= +_TeamID;
return y.Name;
})
})
}
I try so many different way with filter. But never get something good. Never works.
I can make a double .foreach , for each array. but I think a better method exist than making a double loop.
Thanks
Instead of using the filter method (which is in fact working similar as a for loop), you could do forEach on both arrays. For your current data structure, there is no other way around it.
getInfo = (_TeamID) => {
let teamName = '';
this.concessionList$.forEach(entry => {
entry.KnownAs.forEach(team => {
if(team.TeamId === _TeamID){
teamName = team.Name;
return; // break the loop.
}
})
});
return teamName;
}
Here is a working example
https://stackblitz.com/edit/double-for-lopp
EDIT
If you have a look at the polyfill implementation of filter from Mozilla https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter which is in equivalent to the native implementation of filter, you can see that it is looping through the whole array, the same way as a forEach loop. The difference is that the filter method will return a new array based on the boolean condition inside the callback function, while a forEach loop does not return anything.
Assuming myArray is contains the data you provided.
The following code will work if you're using Typescript 3.7 and above.
public getInfo(teamId: number): string | undefined {
const team = this.concessionList$
.map(concession => concession.KnownAs)
.reduce((a, b) => a.concat(b), [])
.find(team => team.TeamId === teamId)
return team ? team.Name : undefined
}
Usage:
this.getInfo(3) // Colorado Rockies
Ok how this work?
You have to understand what is find. For example:
const result = [{name: 'foo', age: 1}, {name: 'bar', age: 2}]
.find(people => people.name === 'foo')
console.log(result) // {name: 'foo', age: 1}
My problem is, that I wrote the following code:
Meteor.methods({
'pushItems': function (itemId) {
var specificValue = "12";
if (this.userId) {
userManagement.update({
'_id': this.userId
}, {
$push: {
'itemIds': itemId,
'values': specificValue
}
}
);
}
}
});
After I called this method, one item with an "itemId" is stored within the array "itemIds" and one item is stored with "12" within the array "values". All of this happens in one user object.
Now, I need to write a function which checks whether "12" is within 'values' of the users and in case this is 'true' it should $pull the chronological first added itemId [0] out of the array 'itemIds'.
The method below will find a document that contains the argument (value) in the values array, and will remove the item at [0] from the itemId array
Meteor.methods({
'pullItems': function (value) {
return userManagement.update(
{ values: value },
{ $pop: { itemId: -1 }}
);
}
});
fiddle: https://jsfiddle.net/ahmadabdul3/L3eeeh6n/
I'm building an app. This app starts with some static data that I can add to, remove from. The problem I'm having (circular dependency) comes from this initial static data. Here's the scenario:
I have 2 services (fruit, basket). Each fruit can belong to only 1 basket, but each basket can hold many fruits. These two services (below) depend on each other:
function fruitService() {}
function basketService() {}
the reason they depend on each other is because of the initial static data that I have:
function fruitService(basketService) {
var data = [
{
id: 0,
name: 'apple',
basket: function() { return basketService.getById(this.refs.basket); },
refs: {
basket: 0
}
}
];
}
as you can see, I have a function basket that returns a basket item, so that I can dynamically retrieve basket objects from fruit objects.
the basket service is similar:
function basketService(fruitService) {
var data = [
{
id: 0,
name: 'basket1',
fruits: function() { return fruitService.getByIdList(this.refs.fruits); },
refs: {
fruits: [0, ...]
}
}
];
}
same as the fruitService, I have a fruits function that can give me fruit objects when I ask for them. I've tried different combinations of ways to try to break apart the actual static data and the service to overcome this circular dependency, but its not happening.
how can I architect this without having this circular dependency
Have one of the services use $injector and do a lookup for the service at runtime
var injectedService = $injector.get('servicenamehere');
You will need to add $injector to your service parameters for this to work (just in case there was any question)
You don't need 2 services. I think that one is enough.
function basketService() {
var data = [
{
id: 0,
name: 'apple',
basketName: 'basket1'
},
];
var service = {
getFruitById: getFruitById,
getBasketById: getBasketById
};
function getFruitById(fruitId){
// return one fruit here
}
function getBasketById(basketId){
// return your basket with a list of fruits
}
}
Another option would be use a constant to store your data.
angular.module('yourApp').Constant("fruitAndBasketConstant", {
baskets : [{
id : 0,
fruits : [
{
// some info
},
{
// some info
}
]
}]
});
And create a service that will query your constant.
angular.module("yourApp").factory("FruitService"["fruitAndBasketConstant", function(fruitAndBasketConstant){
var service = {
getFruitById: getFruitById
};
return service;
function getFruitById(fruitId){
// loop through fruitAndBasketConstant.baskets
// and return the fruit you want
}
}]);
And do the same for your basketService.
I'm working in a collection that contains a model with collections of "itself". For example:
[{
id: 1
name: "John",
children: [
{
id: 32
name: "Peter",
children: []
},
{
id: 54
name: "Mary",
children: [
{
id:12,
name: "Kevin"
}
]
},
]
}]
Let say that I want to get the Kevin "user" by its Id. But all that I have is the "first collection". How can I do that?? And about setting a user within a collection? Another thing: Its possible to get all the Kevin "parents" from him? Like Mary and John?
Does anyone has come to a issue like that?
Thanks a LOT
Well I've made a recursive function on the User's Collection that seems to solved the problem for now ( the best of this is that I can use for retrieve a "deep" model and change it.). Something like that ( if someone has any suggestions, be free to give it a opinion ):
findUserById: function(id) {
var self = new Backbone.Collection(this.toJSON());
return thisCollection(id, this);
function thisCollection(id, collection, array) {
var innerSelf = collection || this;
var thisArray = array || [];
for(var i = innerSelf.models.length; i--;) {
if(innerSelf.models[i].get('id') == id) {
return [innerSelf.models[i]].concat([thisArray]);
}else {
if(innerSelf.models[i].get('children').length > 0) {
thisArray.push(innerSelf.models[i]);
return thisCollection(id, innerSelf.models[i].get('children'), thisArray);
}else {
innerSelf.remove(innerSelf.models[i]);
return thisCollection(id, self, []);
}
}
}
}
}
Basically I return an array with 2 items. The first is the record that I'm looking for and the second is an array with the parents of this user.
Underscore (which is a Backbone dependency, so you already have it) is great for this sort of thing; if you use its "map" function (which Backbone provides as a method on Collection) with its find function, you can do the following:
findPersonInPeopleCollection: function(nameWeAreLookingFor) {
function findChildren(person) {
if (!person.children) return [person];
var children = _.map(person.children, function(child) {
foundPeople.push(findChildren(child);
})
return _.flatten(children);
}
var allPeople = _.flatten(myCollectionOfPeople.map(findChildren));
return _(allPeople).find(function(person) {
return person.get('name') == nameWeAreLookingFor;
}
}
If you wanted to store the parents initially you could either add logic to your "Person" model class's initialize function, eg.
var Person = Backbone.Model.extend({
initialize: function() {
_.each(this.get('children'), function(child) {
child.parent = this;
}, this);
}
});
You could also do something similar by overriding your collection's add method, or adding an event handler to it that triggers after people get added.