There is a product page in the store. The goods are gift card codes. Each has its own price. Cards are bought using a form with buttons for card denominations (each has its own price), which is almost completely unrelated to the product page (the form is in a pop-up, called by clicking on the button), and product cards appeared as a bonus, they were not originally planned. But since there is such a thing, it is necessary to adjust it. The essence of the task is that when you click on the popup call in the form, the button of the required card denomination is clicked. So that the parameters in the form change accordingly. I thought to cling to the url of the product page (in the url there is something like nominal-4000). But I don’t know how to make a comparison so that part of this url is compared with an array of buttons that also have the same class (of type nominal-4000). Here's what I was able to do:
const popupBtn = document.querySelector('.popup-btn');
pb.addEventListener('click', (e) => {
e.preventDefault();
document.body.classList.add('popup-open');
let nominal4000 = document.querySelector('.nominal-4000');
let field = 'nominal-4000';
if(window.location.href.indexOf(field) > -1) {
nominals.forEach(nominal => {
nominal.classList.remove('active-nominal');
if (nominal.classList.contains(field) ) {
nominal4000.click();
nominal4000.classList.add('active-nominal');
}
})
}
Here I'm just looking for the button and the url part of the page by nominal-4000. Works. But there will be 10 total products, and therefore pages and, consequently, buttons. That is, an array is needed. And their comparison, or something else. I have not delved into such wilds of JS yet, I cannot understand what and how. Use for example an array with denominations (they are also part of the url):
var fields = [
'nominal-3000',
'nominal-4000',
'nominal-5000'
];
Then an array with button classes, something like this -
var nominals = document.querySelectorAll(`${fields}`);
Here is a comparison of two arrays
let isFounded = fields.some( ai => nominals.includes(ai) );
But it doesn't all work together. Who fumbles in arrays, help please
Try this
const popupBtn = document.querySelector('.popup-btn');
popupBtn.addEventListener('click', (e) => {
e.preventDefault();
document.body.classList.add('popup-open');
var fields = [
'nominal-3000',
'nominal-4000',
'nominal-5000'
];
var nominals = document.querySelectorAll(`.${fields.join(', .')}`);
fields.forEach(field => {
if(window.location.href.indexOf(field) > -1) {
nominals.forEach(nominal => {
nominal.classList.remove('active-nominal');
if (nominal.classList.contains(field) ) {
nominal.click();
nominal.classList.add('active-nominal');
}
})
}
});
});
Related
I am kinda new to the Velo coding / javascript in general and I am trying to re-create this tutorial --> https://support.wix.com/en/article/velo-tutorial-creating-an-expanding-mega-menu
Without the second menu (only a main menu and a strip with the items like attached screenshot).
I have a problem with javascript and wix coding. Even though I have created the collections correctly for some reason I can not open the site menu correctly. I am also attaching a wix forum link: https://www.wix.com/velo/forum/coding-with-velo/typeerror-cannot-read-properties-of-undefined-reading-filter.
Can not read the data subSubItems{i} from repeaterData, while it has all the necessary data in it
I am also attaching a screenshot of the database inself for review. (Json format on subSubItems) and the wix site itself as of right now: https://giannisliko.wixsite.com/my-site-1
The global page coding is this:
// The code in this file will load on every page of your site
//-------------Imports-------------//
import wixData from 'wix-data';
//-------------Global Variables-------------//
//Number of Submenu 2 repeaters.
const subLevel2RepeaterCount = 5;
//Object containing all menu data from subTitles database collection.
let menuData;
$w.onReady(async () => {
//Get the menu data from the collection.
menuData = await wixData.query("SubTitlesCollection").find().then(result => result.items);
//console.log(menuData);
//Set up each Submenu 2 repeater as it is loaded.
for (let i = 1; i <= subLevel2RepeaterCount; i++) {
$w(`#repeaterSubSub${i}`).onItemReady(($item, itemData, index) => {
//Get the repeater button from its ID.
const repeaterButton = $item(`#buttonSubLevelTwo${i}`)
//Set the item label.
repeaterButton.label = itemData.label;
//Set the item link.
repeaterButton.link = itemData.url;
});
}
});
export function buttonMainMenu_mouseIn(event) {
//Get the ID of the Submenu 1 button the mouse hovers over.
const selectedRootId = event.context.itemId;
//Get all the data of the Submenu 2 related to Submenu 1.
const repeaterData = menuData.filter(item => item.menu === selectedRootId);
const repeaterData2 = menuData.filter(item => item._id === selectedRootId);
console.log(repeaterData2);
//Set up the box element corresponding to the selected button in Submenu 2.
setSubSubMenu(repeaterData);
//Show the Submenu 2 box.
$w('#megaMenuStrip').expand();
}
export function repeaterMainMenu_mouseOut(event) {
}
function createUniqueId() {
//Creating a Unique Id for each of the menu sub-items by getting the current millisecond and adding a random number from 1 to 1000
let id = String(+new Date() + Math.floor(Math.random() * 1000))
return id;
}
function setSubSubMenu(repeaterData) {
//Set the image of the Submenu 1
//$w('#rangeMenuImage').src = repeaterData.img1;
for (let i = 1; i <= subLevel2RepeaterCount; i++) {
//Convert the Submenu 2 string to a Javascript object.
console.log(repeaterData);
console.log(repeaterData[`subSubItems1`]);
const dataSubSub = JSON.parse(repeaterData[`subSubItems${i}`]);
//Set a unique ID for each item.
console.log(dataSubSub);
dataSubSub.forEach(subSubItem => {
subSubItem._id = createUniqueId();
})
//Set the Submenu 2 data in the repeater.
$w(`#repeaterSubSub${i}`).data = dataSubSub;
}
}
export function megaMenuStrip_mouseOut(event) {
$w('#megaMenuStrip').collapse();
}
/**
* Adds an event handler that runs when the mouse pointer is moved
onto the element.
You can also [define an event handler using the Properties and Events panel](https://support.wix.com/en/article/velo-reacting-to-user-actions-using-events).
[Read more](https://www.wix.com/corvid/reference/$w.Element.html#onMouseIn)
* #param {MouseEvent} event
*/
/**
* Sets the function that runs when a new repeated item is created.
[Read more](https://www.wix.com/corvid/reference/$w.Repeater.html#onItemReady)
* #param {$w} $item
*/
Thank you very much in advance
I can't say for sure what's going on, but I can try to point you in the right direction.
If repeaterData is undefined, that means something is probably going wrong on the following line:
const repeaterData = menuData.filter(item => item._id === selectedRootId)[0]
The problem there could be that menuData is undefined, which would mean your query is no good.
Or it could be that none of the item IDs match the selectedRootId. I'm guessing that is the case. Looks like in the tutorial they aren't try to match with item._id like you are doing. It's really hard to tell exactly what's wrong there, but I'm pretty sure that's where your issue is. It could be a problem with your repeater IDs or it could be with the data coming from the collection. Either way, you're not getting any matches there.
so I am trying to make an app that has two search criterias. The front-end app basically fetches data and you have two search bars to filter out the incoming data.
One search is by name and the other is by school name, the tricky part is that the either of the search also takes into account if there is some value in the other search parameter.
For example, if you search for "California University" and "Bob", you should get only Bobs that go to California University to render on the screen. But it seems like right now my DOM only renders the most recent search Ive made. What is the best way to go about a filter that filters both student name and school name using an event listener (keyup) on the search inputs?
searchByNameInput.addEventListener("keyup", (e) => {
const filterNameArray = studentArray.filter((student) => {
// code here to filter students with this name and render it on DOM
}
}
searchBySchoolName.addEventListener("keyup", (e) => {
//filters students who go to this school and render it on DOM
}
}
Write a single filtering function that checks both inputs, and call it from both event listeners.
function filterStudents() {
const nameFilter = searchByNameInput.value;
const schoolFilter = searchBySchoolName.value;
const filterArray = studentArray.filter(student =>
(nameFilter == '' || student.name.includes(nameFilter) &&
(schoolFilter == '' || student.school.includes(schoolFilter))
}
searchByNameInput.addEventListener("keyup", filterStudents);
searchBySchoolNameInput.addEventListener("keyup", filterStudents);
first filter your object and please try it include() method instead of filter().
as a above example
here filterData is my new filtered object and stu_data is my array.
get all search value from search input.
Example:-
var filterData = stu_data.filter((stu_filter) => {
return (stu_filter.firstname.toLowerCase().includes(filter) ||
stu_filter.lastname.toLowerCase().includes(filter))})
I hope this is help for you!
happy coding :)
I built a custom component that filters an array of objects. The filter uses buttons, sets from active to non-active and allows more than one option on/off at the same time.
StackBlitz of my attempt - https://stackblitz.com/edit/timeline-angular-7-ut6fxu
In my demo you will see 3 buttons/options of north, south and east. By clicking on one you make it active and the result should include or exclude a matching "location" either north, south and east.
I have created my methods and structure to do the filtering, I'm struggling with the final piece of logic.
So far I have created a method to create an array of filtered locations depending on what the user clicks from the 3 buttons.
Next this passes to my "filter array" that gets the logic that should compare this filtered array against the original to bring back the array of results that are still remaining.
Its not quite working and not sure why - I originally got this piece of functionality working by using a pipe, but fore reasons do not want to go in that direction.
//the action
toggle(location) {
let indexLocation = this.filteredLocations.indexOf(location);
if (indexLocation >= 0) {
this.filteredLocations = this.filteredLocations.filter(
i => i !== location
);
} else {
this.filteredLocations.push({ location });
}
this.filterTimeLine();
}
// the filter
filterTimeLine() {
this.filteredTimeline = this.timeLine.filter(x =>
this.contactMethodFilter(x)
);
}
//the logic
private contactMethodFilter(entry) {
const myArrayFiltered = this.timeLine.filter(el => {
return this.filteredLocations.some(f => {
return f.location === el.location;
});
});
}
https://stackblitz.com/edit/timeline-angular-7-ut6fxu
Sorry for my expression but u have a disaster in your code. jajaja!. maybe u lost that what u need but the logic in your functions in so wrong. comparing string with objects. filter a array that filter the same array inside... soo u need make a few changes.
One:
this.filteredLocations.push({location});
Your are pushing object. u need push only the string.
this.filteredLocations.push(location);
Two:
filterTimeLine() {
this.filteredTimeline = this.timeLine.filter(x =>
this.contactMethodFilter(x)
);
}
in this function you filter the timeLine array. and inside of contactMethodFilter you call filter method to timeLine again....
See a functional solution:
https://stackblitz.com/edit/timeline-angular-7-rg7k3j
private contactMethodFilter(entry) {
const myArrayFiltered = this.timeLine.filter(el => {
return this.filteredLocations.some(f => {
return f.location === el.location;
});
});
}
This function is not returning any value and is passed to the .filter
Consider returning a boolean based on your logic. Currently the filter gets undefined(falsy) and everything would be filtered out
I am creating a questionnaire type form using ReactJs and Ant Design. It is a follow up question of How to create a questionnaire type form using Ant Design?
Now I am succeeded in adding new questions and their respective answers but not in removing them. Let's suppose I have added three questions and when I am trying to remove any one of them, its always removing the last one. The related code for removing is as follows:
remove = k => {
console.log(k);
const { form } = this.props;
// can use data-binding to get
const keys = form.getFieldValue("keys");
// We need at least one passenger
if (keys.length === 1) {
return;
}
keys.splice(k, 1);
// can use data-binding to set
form.setFieldsValue({
keys: keys
});
console.log(keys);
};
The complete code can be found as a demo on codesandbox.io.
I have done something similar in the past. Got rid of the boilerplate of antd's remove and replaced with this. Every time I add a row I push that row (object) to formRows array then removing like this:
remove = key => {
const newRows = this.state.formRows.filter(r => r.key !== key)
this.setState(
prev => ({
formRows: newRows
})
)
}
I have a list of users, which contains a node called scannedCards, which contains an array of cardIds. Below is a screenshot of one user.
There are multiple users like above, I want to delete all the card Ids if they are equalTo(Some Card Id), I want to this with all the users at once.
Below is the query I a using:
const ref = database.ref('users');
const query = ref.orderByChild('cardId').equalTo(cardId);
But the result is always empty, Can someone please tell how I can achieve this?
The query you listed above doesn't seem to be returning anything because, based on the screenshot provided, cardId isn't a direct child property of users, but rather a property of each object under the scannedCards list that users may have.
If you only need to do this as part of a one-time operation, you may run something like this:
const ref = database.ref('users');
ref.once('value').then(snapshot => {
const users = snapshot.val();
for (var user_id in users) {
const scannedCards = users[user_id].scannedCards;
for (var card in scannedCards) {
if (scannedCards[card].card_id == "<some card id>") {
firebase.database().ref(`users/${user_id}/scannedCards/${card_id}`)
.set(null);
}
}
}
});
If you plan on letting logged-in users delete their scanned cards, it would be a little bit less complicated:
// user_id is for whoever is logged in
const ref = firebase.database().ref(`users/${user_id}/scannedCards`);
ref.once('value').then(snapshot => {
const scannedCards = snapshot.val();
for (var card in scannedCards) {
if (scannedCards[card].card_id == "<some card id>") {
firebase.database().ref(`users/${user_id}/scannedCards/${card_id}`)
.set(null)
}
}
});
Also worth pointing out, scannedCards is not an array of card ids, because the keys are object ids and the values are objects (which contain cardId and userId properties).