I am trying to write a shopping cart app which when we enter a value in search bar it should update the list and show item available based on value entered.
With the code I wrote, everything is working fine until I made a selection of an item which is not updating the view at first time and showing all the channels.(I think state not updating at first time, but doing at second time)
I am pretty new to react. I tried to add only necessary code here for solution.
state = { open: false, value: '', filteredSections: 'none', displaySections: [] };
filterFunction(e, someSections) {
const filteredSections = [];
this.setState({ value: e.target.value });
someSections.forEach((category) => {
const results = [];
const itemCopy = {...category};
category.arraysinside.forEach((item) => {
if (item.name.toLowerCase().includes(e.target.value.toLowerCase())) { results.push(item); }
});
itemCopy.arraysinside = results;
if (itemCopy.arraysinside.length > 0) { filteredSections.push(itemCopy); }
});
this.setState({ filteredSections: filteredSections });
return filteredSections;
}
updateFunction(displaySections) {
this.setState({ displaySections: displaySections });
}
onChange(opt) {
// makes item selected and changes color of item to know that item is selected
}
render() {
const someSections = customization.arraysinside.filter(c => c.has === 'channels');
let { displaySections, filteredSections } = this.state;
return (
<div>
<FormControl
name="search-items"
placeholder="Search items"
onChange={(e) => {
filteredSections = this.filterFunction(e, someSections);
this.setState({
displaySections: filteredSections.length > 0 ? displaySections = filteredSections : 'No',
value: this.state.value,
});
}}
/>
<div>
{displaySections.length > 0 ? displaySections.map(section =>
<someSections
onChange={(opt) => {
onChange(opt);
this.updateFunction(opt, displaySections);
}}
:
someSections.map(section =>
<someSections
onChange={opt => onChange(opt)}
/>)
}
</div>
</div>
);
}
}
JSON FORMAT WILL BE
{
"name": "product 1",
"has": "channels",
"arraysinside": [
{ "selected": false, "name": "Item 1"},
{ "selected": false, "name": "Item 2"},
{ "selected": false, "name": "Item 3"},
{ "selected": false, "name": "Item 4"},
],
},
{
"name": "product 2",
"has": "channels",
"arraysinside": [
{ "selected": false, "name": "Item 1"},
{ "selected": false, "name": "Item 2"},
{ "selected": false, "name": "Item 3"},
{ "selected": false, "name": "Item 4"},
],
},
displaySections should be updated every time I select the item and should change the view instantly, but with current code, It updates when I enter another value or update selection next time. PLease help, I been trying it for days with no improvement. I will be glad, If suggested a easier way than I wrote.
setState() is asynchronous, so try:
this.setState({ value: e.target.value }, () => { ... do stuff relying on value });
What's the best way to create a nested list like this one from nested JSON objects (by list, I mean the < ol > tag or something custom with similar behaviour):
Parent 1
a. Sub 1
b. Sub 2
i.Sub Sub 1
ii.Sub Sub 2
c. Sub 3
Parent 2
As an example let's use a limit of maximum 3 "nesting levels" deep.
The JSON object that would generate this list would look like this:
[
{
"content": "Parent 1",
"children": [
{
"content": "Sub 1",
"children": [...]
},
{
"content": "Sub 2",
"children": [...]
}
]
},
{
"content": "Parent 2"
}
]
try this simplest approach
var obj = [{
"content": "Parent 1",
"children": [{
"content": "Sub 1",
"children": [{
"content": "sub sub 12"
}]
}, {
"content": "Sub 2",
"children": [{
"content": "sub sub 12"
}]
}]
}, {
"content": "Parent 2"
}];
var html = getListHTML(obj);
console.log( html );
$( "body" ).append( html );
function getListHTML(obj)
{
if ( !obj )
{
return "";
}
var html = "<ol>";
html += obj.map(function(innerObj) {
return "<li>" + innerObj.content + "</li>" + getListHTML(innerObj.children)
}).join("");
html += "</ol>";
return html;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You can then give a different starting value (1 or a or i) based on the hierarchy level of li
This is a proposal with an iterative and recursive callback for Array#forEach and with proper element generating on the fly.
function getValues(el) {
var li = document.createElement('li'),
ol;
li.appendChild(document.createTextNode(el.content));
if (Array.isArray(el.children)) {
ol = document.createElement('ol');
el.children.forEach(getValues, ol);
li.appendChild(ol);
}
this.appendChild(li);
}
var data = [{ content: 'Parent 1', children: [{ content: 'Sub 1', children: [] }, { content: 'Sub 2', children: [{ content: 'Sub Sub 1' }, { content: 'Sub Sub 2' }, ] }, { content: 'Sub 3' }] }, { content: 'Parent 2' }],
ol = document.createElement('ol');
data.forEach(getValues, ol);
document.body.appendChild(ol);
So i have build up this json file (http://www.smartbustracking.be/json/data.json) and now i am able to retrieve data. but what i would like to achieve is to filter data based on id with a for loop.
i am able to show one item of a specific id but not all the data related to that specific id.
So have to have a better understanding of what i am trying to explain see the code via jsfiddle -> https://jsfiddle.net/r4gkw1w8/1/
var json= [
{
"id":"1",
"longitude":"4.420556809486086",
"latitude":"51.21703476701095",
"description":"Station van Mechelen",
"busnummer":"14",
"name":"Station Mechelen",
"busuur":"14:45",
"bussen":[
{
"busnummer":"530",
"busnaam":"Aarshot - Tremelo - Keerbergen - Mechelen",
"bushaltes":[
{
"bushalte":"Zandpoortvest",
"aankomstuur":"17:40"
},
{
"bushalte":"Raghenoplein",
"aankomstuur":"17:45"
},
{
"bushalte":"Station perron 13",
"aankomstuur":"17:52"
}
]
},
{
"busnummer":"55",
"busnaam":"Test - Test - Test",
"bushaltes":[
{
"bushalte":"Test 1",
"aankomstuur":"16:40"
},
{
"bushalte":"Test 2",
"aankomstuur":"16:45"
},
{
"bushalte":"Test 3 perron 13",
"aankomstuur":"16:52"
}
]
}
]
},
{
"id":"2",
"longitude":"4.421180",
"latitude":"51.216227",
"description":"Station van Mechelen",
"busnummer":"180",
"name":"Station antwerpen",
"busuur":"14:45",
"bussen":[
{
"busnummer":"630",
"busnaam":"Busnaam 1 ID 2",
"bushaltes":[
{
"bushalte":"dafas",
"aankomstuur":"14:40"
},
{
"bushalte":"fadas",
"aankomstuur":"14:45"
},
{
"bushalte":"afdas perron 13",
"aankomstuur":"14:52"
}
]
},
{
"busnummer":"660",
"busnaam":"Busnaam 2 ID 2",
"bushaltes":[
{
"bushalte":"Test 1",
"aankomstuur":"13:40"
},
{
"bushalte":"Test 2",
"aankomstuur":"13:45"
},
{
"bushalte":"Test 3 perron 13",
"aankomstuur":"13:52"
}
]
}
]
}
];
var bushalte2=$(json).filter(function (i,field){return field.id==2;});
for (var i=0;i<bushalte2.length;i++)
{
$("#bussen").append(bushalte2[i].name + "<br/>");
$("#bussen").append(bushalte2[i].bussen[i].busnummer);
}
So what i basically want is to filter all the data related to a specific id
If i understood you correctly, you need to add additional for loop for all bussen
for (var i=0;i<bushalte2.length;i++)
{
$("#bussen").append(bushalte2[i].name + "<br/>");
for (var j=0; j <bushalte2[i].bussen.length; j++) {
$("#bussen").append(bushalte2[i].bussen[j].busnummer + "<br/>");
}
}
here is updated jsfiddle https://jsfiddle.net/or4e8t3u/
I am trying to wrap my head around Promises, then , when, and everything else that goes along with it. I am not having much success. Here is what I'm trying to accomplish in English, and maybe somebody can crack the code because so far nothing I've written works.
I am writing a SPA (single page app) for mobile devices. Essentially all the content is is one giant HTML page with a bunch of DIV's. However, only one DIV is shown at a time. The user will have a tab bar to click on each of the icons to show/hide DIV's. Think of something like the Apple App Store interface with "Featured", "Top Charts", "Explore", "Search", and "Updates" at the bottom.
Parse database query of table Businesses for 1 business with AppUrl=example.com
Resulting business objectId is used to query table Navigation for all pieces of the navigation. Things like "Home", "About Us", "Menus", "Events", "Contact", etc.
Resulting navigation items are looped to render DIV's with content in them. The content comes from the tables below depending on the Module column:
"Home" = Photos table
"About Us" = Pages table
"Menus" = Lists table
"Event" = Lists table
That's basically it. Pretty simple, but obviously there are nest queries within #4. I don't know if I should be creating one giant object in my queries and then outputting that? Or creating a bunch of different objects with arrays inside of them? Really kind of lost since this style of syntax is different than say PHP. Advice?
Here is my non-database connected version:
app.get('/', function(req, res){
var frontpageImages = [
{ caption:"Eggplant, Prosciutto, and Pesto Pressed Sandwiches.", file:"image01.jpg", position:"15%" },
{ caption:"Pico de Gallo", file:"image02.jpg", position:"75%" },
{ caption:"B.L.A.T Croque Madame", file:"image03.jpg", position:"20%" },
{ caption:"Double Oreo Brownie Cupcake", file:"image04.jpg", position:"80%" },
{ caption:"Baked Chicken Chimichangas with Monterey Jack Cheese Sauce", file:"image05.jpg", position:"20%" }
]
var menu = [
{ divider:"Appetizers" },
{ name:"French Fries", picture:"menu-french-fries", subname:"$4.95" },
{ name:"Loaded Cheese Fries", picture:"menu-cheese-fries", subname:"$7.95" },
{ name:"Gaelic Chips", picture:"menu-gaelic-chips", subname:"$2.95" },
{ name:"Jalapeno Mac n' Cheese", picture:"menu-jalapeno-mac-n-cheese", subname:"$4.95" },
{ name:"Chicken Wings", picture:"menu-chicken-wings", subname:"$8.50" },
{ name:"Irish Nachos", picture:"menu-irish-nachos", subname:"$8.50" },
{ name:"Black & Tan Onion Rings", picture:"menu-onion-rings", subname:"$6.95" },
{ name:"Mac's Quesadillas", picture:"menu-quesadillas", subname:"$8.50" },
{ name:"Banger Bites", picture:"menu-banger-bites", subname:"$7.95" },
{ divider:"Salads" },
{ name:"Caesar Salad", picture:"menu-caesar-salad", subname:"$6.50" },
{ name:"House Salad", picture:"menu-house-salad", subname:"$6.50" },
{ name:"Buffalo Chicken Salad (Grilled or Battered)", picture:"menu-buffalo-chicken-salad", subname:"$8.95" },
{ divider:"Sandwiches & Burgers" },
{ name:"Rueben", picture:"menu-reuben", subname:"$8.50" },
{ name:"Dublin Corned Beef", picture:"menu-corned-beef-sandwich", subname:"$8.50" },
{ name:"Philly Cheese Steak", picture:"menu-philly-cheese-steak", subname:"$8.50" },
{ name:"Grilled Chicken", picture:"menu-grilled-chicken-sandwich", subname:"$8.50" },
{ name:"Club Sandwich", picture:"menu-club-sandwich", subname:"$8.50" },
{ name:"Not-So-Irish Burger", picture:"menu-irish-burger", subname:"$9.95" },
{ name:"Dirty Burger", picture:"menu-dirty-burger", subname:"$7.95" },
{ name:"Aurora Burger", picture:"menu-aurora-burger", subname:"$10.95" },
{ name:"Bleu Cheese Burger", picture:"menu-bleu-cheese-burger", subname:"$11.95" },
{ name:"Additional Burger Toppings", picture:"menu-burger-toppings", subname:"$0.50" },
{ divider:"Irish Favorites & Entrees" },
{ name:"Beer Battered Fish N' Chips", picture:"menu-fish-and-chips", subname:"$11.50" },
{ name:"Bangers And Mash", picture:"menu-bangers-and-mash", subname:"$10.95" },
{ name:"Shepherd's Pie", picture:"menu-shepherds-pie", subname:"$10.95" },
{ divider:"Brunch" },
{ name:"Irish Breakfast", picture:"menu-irish-breakfast", subname:"$11.50" },
{ name:"American Breakfast", picture:"menu-american-breakfast", subname:"$11.50" },
{ name:"Irish Breakfast Roll", picture:"menu-irish-breakfast-roll", subname:"$8.95" },
{ name:"English Muffin, Scrambled Eggs, Cheddar and Irish Rasher", picture:"menu-irish-rasher", subname:"$7.50" },
{ name:"3 Egg Omelette", picture:"menu-omelette", subname:"$6.50" },
{ name:"Eggs Benedict", picture:"menu-eggs-benedict", subname:"$8.50" },
{ name:"3 Pancakes with Maple Syrup", picture:"menu-pancakes", subname:"$6.00" },
{ name:"Grilled Turkey and Swiss", picture:"menu-grilled-turkey-and-swiss", subname:"$7.00" }
];
var drinks = [
{ name: "Bahama Bomb", desc: "Bacardi 151 Rum, Cruzan Coconut Rum, Creme de Banana, Pineapple juice, and Sprite.", subname: "$9.95" },
{ name: "Tropical Margarita", desc: "Grand Marnier, Cruzan Coconut Rum, Blue Curacao, sour mix, and orange juice. Garnished with lemon, lime, and cherry.", subname: "$10.95" },
{ name: "LOL[emonade]", desc: "Absolute Citron, Triple Sec, muddled lemon and simple syrup, sour mix, and Sprite.", subname: "$9.95" }
];
var events = [
{ divider:"Upcoming Events" },
{ name: "Super Bowl Party", subname: "1/28" },
{ name: "Valentine's Singles Party", subname: "2/14" },
{ divider:"Weekly Events" },
{ name: "Hospitality Night", subname: "Monday" },
{ name: "Trivia Night", subname: "Tuesday" },
{ name: "Karaoke with Liam", subname: "Thursday" }
];
res.render('index', {
nav:[
{ name:"Home", title:"Clark's Bar and Grille", url:"home", icon:"home", module:"home", run:"startSlider", source:frontpageImages },
{ name:"Menu", url:"menu", icon:"cutlery", module:"list", source:menu },
{ name:"Drinks", url:"drinks", icon:"glass", module:"list", source:drinks },
{ name:"Events", url:"events", icon:"calendar", module:"list", source:events },
{ name:"Restaurant Info", title:"Restaurant Info", url:"business-info", icon:"info-circle", module:"business-info" },
{ name:"Instagram Feed", title:"Instagram", url:"instagram", icon:"instagram", module:"instagram", run:"startInstagram" },
{ name:"Like and Follow Us", title:"Social Media", url:"social-media", icon:"thumbs-up", module:"social-media-links" },
{ name:"Contact Clark's", title:"Contact Clark's", url:"contact", icon:"envelope", module:"contact" }
]
});
});
When the page renders now, I have the index.ejs loop the nav object and display each DIV (Home, Menu, Drinks, Events, etc). Each array within the nav object has a key called source which returns the objects for them listed above. The page renders perfectly, it's just not connected to a database. I would like to swap all that out with a DB connected version!
I hope this code will help you, that's the best I can suggest with what you provided:
function handleError(message, error) {
//Handle any error here, for example:
console.error(message, error);
res.send(500, message);
}
var responseContent = {
nav: [],
};
getBusiness(); //start fetching data
function getBusiness() {
var businessQuery = /*query to get element AppUrl=example.com*/;
businessQuery.first().then(
getNavigation,
handleError.bind(null, 'error getting business'));
}
function getNavigations(business) {
var navigationsQuery = /*query to get navigation elements*/;
var promises = [];
navigationsQuery.each(function (navigation) {
promises.push(processNavigation(navigation));
}).then(
function () {
Parse.Promise.when(promises).then(
renderResult,
handleError.bind(null, 'error processing navigations'));
},
handleError.bind(null, 'error iterating navigations'));
}
function processNavigation(navigation) {
var promise = Parse.Promise();
var nav = {
name: /*name*/,
url: /*url*/,
};
responseContent.nav.push(nav);
switch (/*module*/) {
case 'Home':
getPhotosContent(/*args*/).then(
function (source) {
nav.source = source;
promise.resolve();
},
function (error) {
promise.reject(error);
}
);
break;
//can do similar code for 'About Us', 'Menus', ...
default:
promise.resolve();
}
return promise;
}
function getPhotosContent(/*args*/) {
var promise = Parse.Promise();
var results = [];
var photosQuery = /*query to get photos*/;
photosQuery.each(function (photo) {
results.push(photo);
}).then(
function () {
promise.resolve(results);
}, function (error) {
promise.reject(error);
}
);
return promise;
}
function renderResult() {
res.render('index', responseContent);
}