for example:
function example({array 1 item x}, {array 2 item x})
I'd imagine I'll need some sort of for loop that passes each item individually with the equivalent item from both arrays.
actual code:
function hide(bool, item) {
if (bool) {
document.getElementById(item).classList.add("hide");
document.getElementById(item).classList.remove("show");
bool = false;
}
}
I need to run this for every id I want to hide and show, so I figured I could put the bools list and items list in an array and individually run them together to eliminate unnecessary redundancy.
If you want to hide and show element using one function call
this will hide or show multiple element by id
function showAndHide(bool, item) {
if (bool.length !== item.length) throw new Error('bool and item length is different')
bool.forEach((bool2, index) => {
if (bool2) {
document.getElementById(item[index]).classList.add("show");
document.getElementById(item[index]).classList.remove("hide");
} else {
document.getElementById(item[index]).classList.add("hide");
document.getElementById(item[index]).classList.remove("show");
}
})
}
Related
I have a list of data in cardData list and I'm looping over it using ngFor to display a card for each item. I want to filter the cards by card-name which is captured in the filterName property.
I also have a custom filter: I'm using checkboxes to select the filterName. When I select one single checkbox it's working fine but I want to be able to select multiple checkboxes and filter accordingly. I would appreciate some help.
<div class="card-list cursor-move" cdkDrag *ngFor="let cardDet of cardData | filter:filterName">
<input type="checkbox" value="{{filterDet.title}}" (change)="filterValue($event.target.value,$event.target.checked)">
enter code here
#Pipe({
name: 'filter',
pure: false
})
#Injectable()
export class FilterPipe implements PipeTransform {
/* #param items List of items to filter
#param term a string term to compare with every property of the list*/
static filter(items: Array<{ [key: string]: any }>, term: string): Array<{ [key: string]: any }> {
const toCompare = term.toLowerCase();
return items.filter(function (item: any) {
for (const property in item) {
if (item[property] === null) {
continue;
}
if (item[property].toString().toLowerCase().includes(toCompare)) {
return true;
}
}
return false;
});
}
transform(items: any, term: string): any {
if (!term || !items) {
return items;
}
return FilterPipe.filter(items, term);
}
}
//filterValue() is called onChange on the checkbox
filterValue(value,checked){
console.log(checked);
if(checked){
console.log(value);
this.filterName = value;
}
else{
this.filterName='';
}
}
Ok so, there are two things you need to do here. First, you need to capture multiple values from your checkboxes. Right now you are just overwriting a string with the latest checked checkbox:
filterValue(value,checked) {
if(checked) {
this.filterName = value;
}
else {
this.filterName='';
}
}
One way you can do this if you are not looking to use any of Angular's existing forms/patterns (which I highly recommend you learn if you're unfamiliar, here are some sources to check out: 1, 2, 3) is to make an Array. Let's pretend you made one and it's called filterNameArray. Now, you should rewrite your method to match the contents of filterNameArray to the checkboxes that are checked:
filterValue(value,checked) {
if(checked) { //add to array
this.filterNameArray.push(value);
}
else { //remove from array
this.filterNameArray = this.filterNameArray.filter(x => x != value);
}
}
As you can see, we are adding a value to the Array when it is checked and removing it when it is not checked. To remove it we are filtering the Array. I've used an arrow function above because it is shorter and easier to read for some people, but if you are not familiar with arrow functions, it is equivalent to this wordier version:
function(x, value) {
if (x == value) {
return false;
}
return true;
}
When we use it with the filter Array function we are telling our code to run that function on every item in the Array (each item is represented by x in my rewritten method above) and return an Array containing only the values that made it return true. Hopefully that makes sense, but please feel free to ask me questions. Moving on!
Now we can assume that we have an Array that contains all the terms to filter the cards on (but remember you still need to pass this properly!). The next step is filter on this Array instead of a string.
return items.filter(function (item: any) {
for (const property in item) {
let cardName = item[property].toString().toLowerCase();
if (item[property] === null) {
continue;
}
if (toCompare.includes(cardName)) {
return true;
}
}
return false;
});
I moved the string manipulation above the if-statements and stored it in a let just so what I did was easier to read. With this change, the card filter is looking through an Array and keeps a card if its name is found.
order.get_orderlines() is an array of three objects.
I want to call the print_xml function everytime I loop on an orderline where product.is_gift_product == true, but I also want to clean the array before.
Each time, I want to remove all other rows except the one I'm looping on.
I tried to remove all key on which I'm looping where product.is_gift_product != true, and when I loop on a orderline on which product.is_gift_product == true, to remove everything after, but this way I'm not printing the same tickets number as of the number of products marked as gift.
// START GIFT PRODUCT MANAGEMENT
var order_saved = order;
order.get_orderlines().forEach( function (orderline, i) {
if (orderline.product.is_gift_product != true) {
order.get_orderlines().splice(i, 1);
order_saved = order;
} else {
order.get_orderlines().splice(i, 9e9);
setTimeout(function(){
self.print_xml_gift(order, 'XmlGiftReceipt');
order._printed = true;
}, 2000);
}
});
// END GIFT PRODUCT MANAGEMENT
Try chaining a .filter(orderLine => orderLine.product.is_gift_product) before calling your forEach.
you should filter all elements to take a gift products.
During filtering, you can call for print of them.
const order_saved = order.get_orderlines().filter(orderline =>
orderline.product.is_gift_product).forEach(() => {
setTimeout(function(){
self.print_xml_gift(order, 'XmlGiftReceipt');
order._printed = true;
}, 2000);
});
I'm not sure if you need this timeout
SAPUI5 - I have an array of objects and one of the properties in those is 'Category'.
For example say I have 2 different types of Category, 'Front Shop' and 'Production Area', what I need to do is to be able to get the first value of each and the last value of each, and then set the enabled property of a button as enabled/disabled.
I'm currently using undercore js (_.each) to loop through to perform some other logic, so can include additional logic here.
Not sure if Underscore has a built in function for this?
Or could someone point me in the right direction on how to do this?
I've got my first pass at what was wanted where I get the very first result and the last result, but now need to set this for each unique category.
Example code below:
// Set view data
oViewData.Questions = oQuestions.results;
oViewData.Questions.TotalNumberOfQuestions = oQuestions.results.length;
// Loop Questions, to get Category Desc and Competency Desc values from relevant Sets
_.each(oViewData.Questions, function (result, index) {
// Read and set Category Desc
this.getView().getModel("Survey").read("/CategorySet", {
filters: [new Filter("CategoryId", FilterOperator.EQ, result.CategoryId)],
success: function (oData) {
oViewData.Questions[index]._CategoryDesc = oData.results[0].CategoryDesc;
this.setViewData(oViewData);
}.bind(this),
error: function (oError) {}.bind(this)
});
// Read and set Competency Desc
this.getView().getModel("Survey").read("/CompetencySet", {
filters: [new Filter("CompetencyId", FilterOperator.EQ, result.CompetencyId)],
success: function (oData) {
oViewData.Questions[index]._CompetencyDesc = oData.results[0].CompetencyDesc;
this.setViewData(oViewData);
}.bind(this),
error: function (oError) {}.bind(this)
});
// Set all move up / down buttons to enabled
oViewData.Questions[index]._MoveUpBtn = true;
oViewData.Questions[index]._MoveDownBtn = true;
// if category id is the first one in the list
}.bind(this));
// Overwrite first move up button and last move down btn to disabled
oViewData.Questions[0]._MoveUpBtn = false;
oViewData.Questions.slice(-1)[0]._MoveDownBtn = false;
// Set view data
this.setViewData(oViewData);
First, you can iterate through arrays with native JavaScript.
_.each(array, function(item) {}) is the same as array.forEach(function(item) {}).
Second, you can use the built-in filter function for your actual question:
const aFrontShopItems = oViewData.Questions.filter(function(oItem) {
return oItem.Category === "Front Shop";
}
If oViewData.Questions is an array then the function passed to filter is applied to every element. If the condition (e.g. oItem.Category === "Front Shop") is true then the element is added to the new array aFrontShopItems. Obviously you need to call filter a second time to get the Production Area items. You can then apply your logic to the first and last items of your new arrays.
I am using Vue JS, I have 2 different arrays categories and items. Each item can belong to multiple categories, the items are generated dynamically and therefore not initially associated in the category array. Then I parse the category array to create tables containing the different items.
For testing purposes, I attach the items to it's associated category in the mounted vue property, as follows:
mounted: function() {
for (let item of this.items) {
for (let category of item.categories) {
this.categories[category - 1].items.push(item)
}
}
}
Then when the delete button is pressed, I trigger a deleteItem method which uses splice to delete the item from the categories array and from the items array as well, but I am having a little issue there that the correct item does not get deleted.
methods: {
deleteItem: function(item) {
for (let category of item.categories) {
this.categories[category - 1].items.splice(this.categories[category - 1].items.indexOf(item, 1))
}
this.items.splice(this.items.indexOf(item, 1))
}
}
Please see the example Fiddle. Any help will be appreciated.
Change
this.items.splice(this.items.indexOf(item, 1))
to
this.items.splice(this.items.indexOf(item), 1)
so that you pass 1 as second argument to splice.
Note that you do the same error twice.
I'm trying to select the last messages of an inbox and group them in a list by the topic_id. i want to display the last message of each topic.
the array looks like this:
[{
"id":"5",
"topic_id":"4",
"message_from":"24",
"message":"how do you do?",
"date":"2015-01-13 15:34:59"
},
{
"id":"6",
"topic_id":"1",
"message_from":"33",
"message":"go go go!!",
"date":"2015-01-13 13:35:06"
},
{
"id":"7",
"topic_id":"4",
"message_from":"33",
"message":"Je suis charlie",
"date":"2015-01-14 16:24:46"
},....
is there a solution to do it without a loop?
You can't do this without loops, but you can make this easier by breaking down the sequence of events into smaller functions. You might not like this approach, but it's the cleanest imo. Alternatively you can use a third-party library (underscore, perhaps?) that allows you to run groupings on data.
Basically, get a list of all the topic_ids for all records, loop over that topic_id array and pull out the last record for each and add that to an output array.
// Get a list of all the topic ids - no duplicates
function getTopicIds(arr) {
var out = [];
arr.forEach(function (el) {
if (out.indexOf(el.topic_id) === -1) out.push(el.topic_id);
});
return out;
}
// Given a topic_id, filter the array for only those records
// sort in desc order by id, and return the first record.
// Given that each record has a unique id, and we know that older
// messages will have higher ids, it's easier to sort by id than
// date here
function getLastMsg(id, arr) {
return arr.filter(function (el) {
return el.topic_id === id;
}).sort(function (a, b) { return +b.id - +a.id; })[0];
}
// return a array of the last messages for each topic_id
// in the records array
function getLastMsgs(arr) {
return getTopicIds(arr).map(function (id) {
return getLastMsg(id, arr);
});
}
var result = getLastMsgs(arr);
DEMO