How can we filter an ArrayList in Silverstripe 3?
where getVideosfromCategories() returns a merged ArrayList
I need something Like:
$this->getVideosfromCategories()->filter('ID:LessThan', $id)->sort(array('ID' => 'DESC'))->first()
these Filters (filter('ID:LessThan', $id)) only work with DataList ?
How can i filter my ArrayList?
these Filters (filter('ID:LessThan', $id)) only work with DataList ?
Yep, that's correct, search filter modifiers only work on DataList instances.
(https://docs.silverstripe.org/en/3/developer_guides/model/searchfilters/) It's interesting that the documentation does not mention that, I think it should be updated.
(I opened a PR for it https://github.com/silverstripe/silverstripe-framework/pull/9363)
But you can modify your current code to filter by an array of IDs instead, something like this:
$idsWeWant = [];
if ($id > 0) {
$idsWeWant = range(0, $id - 1); // "$id - 1" because you had "LessThan" modifier.
}
$this->getVideosfromCategories()
->filter('ID', $idsWeWant)
->sort(array('ID' => 'DESC'))
->first();
Related
I have sql jsonb column in db named 'car' with structure
[{'brand':'audi', 'year':'2001'}] --> how to filter WHERE brand=audi?
this doesn't seem to be right:
return await db(db_table)
.select('*')
.whereRaw('car->>$.?? = ?', ['brand', 'audi']);
#felixmosh
Since your object is an array of objects, your suggested code won't work.
Try something like this:
return await db(db_table)
.select('*')
.whereRaw('car->>$[0].?? = ?', ['brand', 'audi']);
// ----------------^ this selects the first element of the array
I have a function called updateAnswer with multiple dynamic parameters.
updateAnswer(key, answer, array = false) {
if (array) {
if(this.answers.contains.find(element => element === answer)) {
//Delete item from array if already element already exists in this.answers.contains array.
} else {
Vue.set(this.answers, key, [...this.answers.contains, answer]);
}
} else {
Vue.set(this.answers, key, answer);
}
},
I'd like to know how delete an item in the array if the value already exists in the array.
You can use method called splice:
Just reference on your array and set values in the brackets the first is referenced on the position, the second is how many datas you want to splice/delete.
The function looks like this:
this.array.splice(value, value)
Lets see on an example - you have array food= [apple, banana, strawberry] than I'm using this.food.splice(1,1)..
my array looks now like this food = [apple, strawberry] - first value in my brackets are the position, the second one is the amount of "numbers" you want to delete.
Hopefully this helps you out!
I suppose each value in this.answers.contains is unique?
Anyways, if you just want to delete the item if already exists, I suggest filter(). It should look like below:
if(this.answers.contains.find(element => element === answer)) {
this.answers.contains = this.answers.contains.filter(c => c !== answer)
}
Also, the if condition if(this.answers.contains.find(element => element === answer)) could also be replaced by if(this.answers.contains.includes(answer))
Hope that could help you.
I am trying to create a reactive filter for an array in Vue. My starting array comes from an API call which returns this.features (geojson features). I am filtering on a nested array. This works -- but when I enter a search term and then backspace back out to an empty string, and enter another string, I am not filtering the original array but appear to be filtering the already-filtered array. How could I filter again on the original array from the API call?
computed property:
filteredFeatures() {
if (this.searchTerm == '') {
return this.features
}
// filter on nested array
let filtered = this.features.filter(feature => {
feature.properties.site_observations = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
return feature.properties.site_observations.length > 0
})
return filtered
}
I have looked at Vue filtering objects property but I cannot make that code work (it uses Object.assign()). Thanks for any ideas.
Your computed property is mutating feature.properties.site_observations, that's a nono. Computed properties should be read only.
filteredFeatures() {
if (this.searchTerm == '') {
return this.features
}
// filter on nested array
let filtered = this.features.filter(feature => {
const site_observations = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
return site_observations.length > 0
})
return filtered
}
It seems here is your problem:
feature.properties.site_observations = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
Because this code filter feature and alter the proprieties of feature.properties.site_observations. Then, in the next read the value is alter. We say that your function it is not pure, because it alter the state of feature.
So, what you should do is:
let anotherVariable = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
Therefore, on a function, avoid alter state of objects, this lead to bugs.
On further checking, the above answer returns all site_observations, not just the ones that match the search. A much better solution is the following, using map to avoid overwriting the data, and the object spread operator to perform an object assign, and drilling down through the nested objects as follows:
filteredFeatures() {
return this.features
.map(feature => ({
...feature,
properties: {
site_observations: feature.properties.site_observations.filter(
element => {
return JSON.stringify(element).match(new RegExp(this.search, 'i'))
}
)
}
}))
.filter(feature => feature.properties.site_observations.length)
}
i have an custom extension, where you can select the different entries at the backend, to show them at the list view. I have a custom sorting at my backend, but the system always sort them Descending.
I implemented an "orderBy" function, which doesnt work, because the system uses wrong backspaces.
My code looks like this:
I call the sort function in my "findByUid($uid)" function like this:
$query->setOrderings($this->orderByKey('uid', $uidArray));
protected function orderByKey($key, $uidlist) {
$order = array();
foreach ($uidlist as $uid) {
//$order["$key=$uid"] = \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING;
$order["$key=$uid"] = "ASC";
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($order);
}
return $order;
}
The result at the sql query is:
ORDER BY `tx_MYEXTENSION_domain_model_FIELD`.`uid=3` DESC
But it must be:
ORDER BY `tx_MYEXTENSION_domain_model_FIELD`.`uid` = 3 DESC
Is there a way to change this?
After a lot of search, I found this solution on an stackoverflow entry:
$ids = explode(',',$this->settings['entries'])
foreach($ids as $key => $id){
$entries[$id] = $this->entriesRepository->findByUid($id);
}
This code snippet has to be intergrated at the controller.
For me its working.
This is my code looks like right now :
$result = Category::with(array(
"getProducts",
"getProducts.getBrand",
"getProducts.getImages",
"getProducts.getDetail",
"getProducts.getTax",
"getProducts.getDiscount",
"getProducts.getAttributes" => function($query) use($_temp){
if($_temp != null){
$query->where_in('attributes.id',$_temp);
}
},
"getSlideshow",
"getSlideshow.getItems",
"getAttributeListing",
"getAttributeListing.getAttributes",
"getAttributeListing.getAttributes.productSpecific"
))
->where('id','=', $category_id)
->first();
Yet, It only filters the getProducts.getAttributes items not the 'getProducts' itself. Is there a way that I can get the Products by attributes?
Note: I am using Laravel 3