Vue.js computed property does not works with big array - arrays

I have a computed property witch looks inside a items: {} array, this array have 26 objects inside. The property only "read" the first 23 objects, the 24 and the next ones looks out of the filter range.
Before this conclusion i think the problem is because the 24 object have an special character but i revert the array order and the special character was filter correctly.
items: [
{...},
23: {
alias: "Correcto",
id: 11
},
24: {
alias: "Tamaño",
id: 12
}
25: {
alias: "silla",
id: 13
]
};
This is the code of my filter as a computed: porperty
computed: {
filteredItems() {
if (this.items) {
return this.items.filter((item) => {
if (!this.search) return '';
return item.alias.toLowerCase().match(this.search.toLowerCase().trim());
});
}
}
},
How can i make the filter works with big arrays?

Array's filter method does not has a limitation, the problem here it's the .match() method which check by regex, replace it with .includes() which search if the string passed as parameter occours in the desired string.
.includes() Docs MDN
Little example emulating "large" data
new Vue({
el: '#example',
computed: {
filteredItems () {
return this.items.filter(i => i.alias.toLowerCase().includes(this.filterText.toLowerCase()))
}
},
data () {
return {
filterText: '',
items: [
{
alias: "it\'s working",
id: 1
},
{
alias: "lool",
id: 2
},
{
alias: "vue is awesome",
id: 3
},
{
alias: "another text",
id: 4
},
{
alias: "some value",
id: 5
},
{
alias: "teest",
id: 6
},
{
alias: "bar",
id: 7
},
{
alias: "foo",
id: 8
},
{
alias: "silla",
id: 9
},
{
alias: "Corrécto",
id: 10
},
{
alias: "Tamaño",
id: 11
},
{
alias: "ñoo",
id: 12
},
{
alias: "silla",
id: 9
},
{
alias: "Corrécto",
id: 10
},
{
alias: "Tamaño",
id: 11
},
{
alias: "ñoo",
id: 12
},
{
alias: "silla",
id: 9
},
{
alias: "Corrécto",
id: 10
},
{
alias: "Tamaño",
id: 11
},
{
alias: "ñoo",
id: 12
},
{
alias: "silla",
id: 9
},
{
alias: "Corrécto",
id: 10
},
{
alias: "Tamaño",
id: 11
},
{
alias: "ñoo",
id: 12
},
{
alias: "silla",
id: 9
},
{
alias: "Corrécto",
id: 10
},
{
alias: "Tamaño",
id: 11
},
{
alias: "ñoo",
id: 12
},
{
alias: "silla",
id: 9
},
{
alias: "Corrécto",
id: 10
},
{
alias: "Tamaño",
id: 11
},
{
alias: "ñoo",
id: 12
}
]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.15/vue.js"></script>
<div id="example">
<input type="text" v-model="filterText" />
<ul>
<li v-for="item in filteredItems">{{ item.alias }}</li>
</ul>
</div>

If you mean that you can't get a match when searching strings with characters outside of a-Z range. A basic solution could be to use js charCodeAt function that converts characters to UTF-16 codes. Below is a basic example:
function encodeString(str) {
return str.split('').map(letter => letter.charCodeAt(0)).join('~'); // ~ is to split chars and not to let one mix with other acidentally
}
so your code might actually look something like this:
...
computed: {
filteredItems() {
if (this.items) {
return this.items.filter(item => {
if (!this.search) return false;
return this.isMatching(item.alias, this.search);
});
}
}
},
methods: {
...
encodeString(str) {
return str.split('').map(letter => letter.charCodeAt(0)).join('~');
},
isMatching(haystack, keyword) {
haystack = haystack.toLowerCase().trim();
keyword = keyword.toLowerCase().trim();
return this.encodeString(haystack).match(this.encodeString(keyword));
},
...
}
...

Related

How to get a field and a field into of array in MongoDB

I have this json in MongoDB:
{
_id: ObjectId("630fbb09cc9deb16a33fbcde"),
firmness: {
name: 'hard',
url: 'https://pokeapi.co/api/v2/berry-firmness/3/'
},
flavors: [
{
flavor: {
name: 'spicy',
url: 'https://pokeapi.co/api/v2/berry-flavor/1/'
},
potency: 10
},
{
flavor: {
name: 'dry',
url: 'https://pokeapi.co/api/v2/berry-flavor/2/'
},
potency: 0
},
{
flavor: {
name: 'sweet',
url: 'https://pokeapi.co/api/v2/berry-flavor/3/'
},
potency: 0
},
{
flavor: {
name: 'bitter',
url: 'https://pokeapi.co/api/v2/berry-flavor/4/'
},
potency: 0
},
{
flavor: {
name: 'sour',
url: 'https://pokeapi.co/api/v2/berry-flavor/5/'
},
potency: 10
}
],
growth_time: 2,
id: 20,
item: { name: 'pinap-berry', url: 'https://pokeapi.co/api/v2/item/145/' },
max_harvest: 10,
name: 'pinap',
natural_gift_power: 70,
natural_gift_type: { name: 'grass', url: 'https://pokeapi.co/api/v2/type/12/' },
size: 80,
smoothness: 20,
soil_dryness: 35
}
And I want to get the soil_dryness field and the field called "name" into flavor list from 'flavors' array.
How can I do that?
I tried with:
db.Berries.find({},{soil_dryness:1},{"flavors.$":1}).pretty().limit(20)
But unfortunately doesn't works.
Query
project, the soil_dryness and the names, path in arrays = array with the values, here the names
*not sure if this the output you need, if its not if you can add the expected ouput you need
Playmongo
db.Berries.aggregate(
[{"$project": {"soil_dryness": 1, "names": "$flavors.flavor.name"}},
{"$limit": 20}])

covert list into another new list with new property name

I have one list look like allsettings. I want to convert that list to a new list. Since I am new to react I don't have much idea, I tried by doing the below way but 1st item in the new list is always empty.
const [mySetting, setMySet] = useState([]);
useEffect(() => {
const allSettings = [
{ name: "Setting1", value: true, label: 1 },
{ name: "Setting2", value: true, label: 2 },
{ name: "Setting3", value: true, label: 3 },
{ name: "Setting4", value: false, label: 4 },
{ name: "Setting5", value: true, label: 5 },
{ name: "Setting6", value: true, label: 6 },
{ name: "Setting7", value: true, label: 7 }
];
const settings = [];
const allSettingsMap = allSettings.reduce((resMap, current) => {
settings.push(resMap);
return {
...resMap,
SettingID: current.label,
Name: current.name,
value: current.value
};
}, {});
setMySet(settings);
}, []);
//I want new list like this:
const newSettings = [
{ name: "Setting1", value: true, SettingID: 1 },
{ name: "Setting2", value: true, SettingID: 2 },
{ name: "Setting3", value: true, SettingID: 3 },
{ name: "Setting4", value: false, SettingID: 4 },
{ name: "Setting5", value: true, SettingID: 5 },
{ name: "Setting6", value: true, SettingID: 6 },
{ name: "Setting7", value: true, SettingID: 7 }
];
You can use array#map to rename a key in your object and keeping other keys intact. For each object, you can pick label and rename it to SettingID and keep other key-values same.
const allSettings = [ { name: "Setting1", value: true, label: 1 }, { name: "Setting2", value: true, label: 2 }, { name: "Setting3", value: true, label: 3 }, { name: "Setting4", value: false, label: 4 }, { name: "Setting5", value: true, label: 5 }, { name: "Setting6", value: true, label: 6 }, { name: "Setting7", value: true, label: 7 } ],
result = allSettings.map(({label, ...other}) => ({...other, SettingID: label}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can easily do it by map on array
const allSettings = [
{ name: "Setting1", value: true, label: 1 },
{ name: "Setting2", value: true, label: 2 },
{ name: "Setting3", value: true, label: 3 },
{ name: "Setting4", value: false, label: 4 },
{ name: "Setting5", value: true, label: 5 },
{ name: "Setting6", value: true, label: 6 },
{ name: "Setting7", value: true, label: 7 }
];
const newAllSettings = allSettings.map(item => {
return {
name: item.name,
value: item.value,
SettingID:item.label
};
});
console.log(newAllSettings)
Replace your allSettings.reduce method with this map method
const settings = [];
allSettings.map((setting) => {
const item = { ...setting };
const tempValue = item?.label;
// delete item label
delete item["label"];
item["SettingID"] = tempValue;
settings.push(item);
});

Angular 2 pipe to filter grouped arrays

I have a group of arrays on my Angular2 app that I use to build a grouped list with *ngFor in my view:
[
{
category: 1,
items: [{ id: 1, name: "helloworld1" }, { id: 2, name: "helloworld2" }]
},
{
category: 2,
items: [{ id: 3, name: "helloworld3" }, { id: 4 }]
},
{
category: 3,
items:[{ id: 5 }, { id: 6 }]
}
]
I also have a boolean that when it's true should filter only the items that have the name property. If a group does not have any item that matches this condition it should not pass. So the result would be the following if the boolean is true:
[
{
category: 1,
items: [{ id: 1, name: "helloworld1" }, { id: 2, name: "helloworld2" }]
},
{
category: 2,
items: [{ id: 3, name: "helloworld3" }]
}
]
How can I implement a pipe to achieve this kind of result?
http://plnkr.co/edit/je2RioK9pfKxiZg7ljVg?p=preview
#Pipe({name: 'filterName'})
export class FilterNamePipe implements PipeTransform {
transform(items: any[], checkName: boolean): number {
if(items === null) return [];
let ret = [];
items.forEach(function (item) {
let ret1 = item.items.filter(function (e) {
return !checkName || (checkName && (e.name !== undefined));
});
if(ret1.length > 0) {
item.items = ret1;
ret.push(item);
}
});
return ret;
}
}

Can't get $http.get to work in Ionic app

I'm trying to build my first Ionic app and to use a simple list population using $http.get and JSON. What I have is this:
.controller('ReportTabCtrl', function($scope) {
$scope.items = [
{ id: 0 },
{ id: 1 },
{ id: 2 },
{ id: 3 },
{ id: 4 },
{ id: 5 },
{ id: 6 },
{ id: 7 },
{ id: 8 },
{ id: 9 },
{ id: 10 },
{ id: 11 },
{ id: 12 },
{ id: 13 },
{ id: 14 },
{ id: 15 },
{ id: 16 },
{ id: 17 },
{ id: 18 },
{ id: 19 },
{ id: 20 },
{ id: 21 },
{ id: 22 },
{ id: 23 },
{ id: 24 },
{ id: 25 },
{ id: 26 },
{ id: 27 },
{ id: 28 },
{ id: 29 },
{ id: 30 },
{ id: 31 },
{ id: 32 },
{ id: 33 },
{ id: 34 },
{ id: 35 },
{ id: 36 },
{ id: 37 },
{ id: 38 },
{ id: 39 },
{ id: 40 },
{ id: 41 },
{ id: 42 },
{ id: 43 },
{ id: 44 },
{ id: 45 },
{ id: 46 },
{ id: 47 },
{ id: 48 },
{ id: 49 },
{ id: 50 }
];
});
And this works great. The list is populated as it should. What I want is to move the contents of $scope.items to an external file (to be able to generate it dynamically) and call it using $http.get.
I've tried this without any success:
.controller('ReportTabCtrl', function($scope, $http) {
$http.get('items.json')
.success(function(data) {
$scope.items = data;
})
});
The content of the items.json file is the same as the $scope.items variable.
What am I doing wrong?
/Carl
You need to put " double qoutes aside id property in each element of items.json to make it valid json
items.json
[
{ "id": 0 },
{ "id": 1 },
{ "id": 2 }
// and so on
//.
//.
]
Demo Plunkr
I would also read this previous thread AngularJS: factory $http.get JSON file.
There are a couple things that could be going wrong for you.

Unable to use variable in angularjs ng-include

i build a list using .factory and in every elemt have a arrtibute which store page which needed to be include when clicked on any list item
.
i am unable to use this attribute dynamiclly ..plzz help,,,,
i am using ionic framework
////////////// service.js ////////////////
angular.module('starter.services', [])
.factory('Ctopic', function() {
// Might use a resource here that returns a JSON array
// Some fake testing data
var chats = [ { title: 'Arrays', id:11 ,desc: "'ctopic/Union.html'"},
{ title: 'Bit Field Declaration', id:12 },
{ title: 'C Pointers', id: 13 },
{ title: 'Conditional Statements', id: 14 },
{ title: 'File IO', id: 15 },
{ title: 'Function', id: 16 },
{ title: 'Input & Output', id: 17 },
{ title: 'Loops', id: 18 },
{ title: 'Preprocessor Operators', id: 19 },
{ title: 'Preprocessor', id: 20 },
{ title: 'String', id: 21 },
{ title: 'Structures', id: 22 },
{ title: 'Typedef', id: 23 },
{ title: 'Union', id: 24 }];
return {
all: function() {
return chats;
},
remove: function(chat) {
chats.splice(chats.indexOf(chat), 1);
},
get: function(chatId) {
for (var i = 0; i < chats.length; i++) {
if (chats[i].id === parseInt(chatId)) {
return chats[i];
}
}
return null;
}
};
});
/////// html page /////////
<ion-view view-title="{{chat.title}}">
<ion-content class="padding">
{{chat.id}}
{{chat.desc}}
<div ng-include="{{chat.desc}}"></div>
</ion-content>
</ion-view>
Don't use the brackets for ng-include:
<div ng-include="chat.desc"></div>

Resources