Add additional matching between two arrays to - javascript

Here's what I want to achieve. I've 2 arrays, one for artists and one for releases. I am currently matching "ArtistID" to each to display "Releases by this artists" on my SingleArtist page. However I want to take it a step further and add another identifier if the release features them. Example : release A has artist A, but a remixer B. Is there a way to do it within by doing more filtering on the arrays(s)? Not sure how to go about it. Thanks.
example from releases.json
{
"id": 9,
"artistID": "SU",
"featuredartist": "ES, FG",
"imageURL": "../images/releases/dulcie.jpg",
"title": "Dulcie Caught a Cricket",
"description": "Released 2020",
"artist": "Sumsuch",
"buy": "https://www.beatport.com/release/we-choose/1916121",
"stream": "https://open.spotify.com/album/4cutoknbgciTGGpAYSZXfK?si=gsNvR6ytTN6KdrPORfSLOg"
},
example from artists.json (the second object is a remixer 'id:0' who is featured on 'id:3' and would like that to display under the "ES" releases
{
"id": 3,
"artistID": "SU",
"imageURL": "./images/sumsuch.jpg",
"singleimageURL": "../images/artists/sumsuch.jpg",
"name": "SUMSUCH",
"bio": "Will Sumsuch has been a musician, producer and DJ",
"soundcloud": "sumsuch"
},
{
"id": 0,
"artistID": "ES",
"imageURL": "./images/artists/ericblue.jpg",
"singleimageURL": "../images/artists/ericblue.jpg",
"name": "ERIC SHANS",
"bio": "A producer and DJ residing in Brooklyn, NY,
},
code for singleartist.js (abbreviated)
function SingleArtist() {
const { id } = useParams() //finds single artist from array & matches ID
const artist = artists.find((a) => a.id === +id)
//finds ArtistID from Artists then matches any item that has the same value from the Releases array
const releaseList = releases.filter((b) => b.artistID === artist.artistID)
const { singleimageURL, name, soundcloud, bio } = artist
return (
<Wrapper>
<div className="artist-container">
<div className='item'>
<div className='image'>
<img className='artist' src={singleimageURL} alt={name} />
</div>
<div className="description">
<p className='name'>
{name}
</p>
<p className='bio'>
{bio}
</p>
</div>
<a href={'https://soundcloud.com/' + soundcloud} target="_blank" rel="noreferrer">
Listen to {name}'s Soundcloud
</a>
</div>
</div>
<span>
<Link className='link-back' to="/artists"> Back To Artists</Link>
</span>
<div className="matches">
<h4> Releases by {name} </h4>
{releaseList.map(release => {
const { imageURL, name, id, buy } = release;
return (
<div className="item" key={id}>
<a href={buy} target="_blank" rel="noreferrer">
<img className="image" src={imageURL} alt={name} />
</a>
</div>
)
})}
</div>
</Wrapper>
)
}

The way I understand your question, you simply want to find a list of releases that an artist is featured in on the single artist page. This line should do the trick:
let releases = [{
"id": 9,
"artistID": "SU",
"featuredartist": "ES, FG",
},{
"id": 3,
"artistID": "ED",
"featuredartist": "SU, FG",
}]
const featuredList = releases.filter(release => release.featuredartist.split(", ").includes("SU"));
console.log(featuredList);
You can insert this directly below the line where you set releaseList. It is basically the same idea. This line filters the releases again, and then splits the featuredartists string into an array of strings. Then, if the array includes the artist's id, you return it.

Related

How to sort JSX elements from JSON values

What I Want to Do:
I want to render a list of elements using .map, then sort by most recent on top. I've tried adding .sort and .filter before rendering the element, but it doesn't seem to be working. I've done some quick Google searches, but came across posts which don't seem relevant to what i'm trying to do. (or it's just me).
I want to sort by date, with the most recent on top.
Render Component:
import React from "react";
import TransactionEntry from "./TransactionEntry";
function Transactions({ transactionList }) {
return (
<div className="flex flex-col items-start justify-start w-full h-[520px] overflow-auto gap-3 no-scrollbar">
{transactionList.map((transaction) => {
return (
<TransactionEntry
id={transaction.id}
retailer={transaction.retailer}
category={transaction.category}
price={transaction.price}
dateAdded={transaction.dateAdded}
/>
);
})}
</div>
);
}
export default Transactions;
Data Structure:
[
{
"id": "ts001",
"category": "Category",
"retailer": "Retailer",
"price": 1.99,
"dateAdded": "04/02/01"
},
{
"id": "ts002",
"category": "Category",
"retailer": "Retailer",
"price": 13.99,
"dateAdded": "04/02/04"
},
{
"id": "ts003",
"category": "Category",
"retailer": "Retailer",
"price": 119.99,
"dateAdded": "04/02/09"
}
]
You can sort before mapping in this way
{transactionList.sort((a, b) => new Date(a.dateAdded) - new Date(b.dateAdded)).map((transaction) => {
return (
<TransactionEntry
id={transaction.id}
retailer={transaction.retailer}
category={transaction.category}
price={transaction.price}
dateAdded={transaction.dateAdded}
/>
);
})}

Build Netflix footer dynamically with Reactjs

I'm trying to build the footer of Netflix dynamically with Reactjs and styled components but i couldn't figure it out how to do it. Any help would be apprciated :)
I created the links in a links.json file
[
{
"id": 1,
"link": "FAQ"
},
{
"id": 2,
"link": "Investor Relations"
},
{
"id": 3,
"link": "Privacy"
},
{
"id": 4,
"link": "Speed Test"
},
{
"id": 5,
"link": "Help Center"
},
{
"id": 6,
"link": "Jobs"
},
{
"id": 7,
"link": "Cookie Preferences"
},
{
"id": 8,
"link": "Legal Notices"
},
{
"id": 9,
"link": "Account"
},
{
"id": 10,
"link": "Ways to Watch"
},
{
"id": 11,
"link": "Coorporate Information"
},
{
"id": 12,
"link": "Only on Netflix"
},
{
"id": 13,
"link": "Media Center"
},
{
"id": 14,
"link": "Terms of use"
},
{
"id": 15,
"link": "Contact US"
}
]
Then in my footer component I tried to perform the filter and map functions but i can't implement the code: it only display 4 items per column inside a ul tag :(((
import React from 'react'
import linksData from '../fixtures/links'
import './Footer.css'
function Footer() {
return (
// <div>
// {linksData
// .filter()
// .map((item, index)=>(
// <li key={index}>{item.link}</li>
// )
// )}
// </div>
<div className="site-footer-wrapper">
<div className="site-footer">
<p className="footer-top">
<a className='footer-top-a' href> Questions? Contact US</a>
</p>
<ul className='footer-links'>
<li className='footer-link-item'>FAQ</li>
<li className='footer-link-item'>Investor Relations</li>
<li className='footer-link-item'>Privacy</li>
<li className='footer-link-item'>Speed Test</li>
</ul>
<ul className='footer-links'>
<li className='footer-link-item'>FAQ</li>
<li className='footer-link-item'>Investor Relations</li>
<li className='footer-link-item'>Privacy</li>
<li className='footer-link-item'>Speed Test</li>
</ul>
<ul className='footer-links'>
<li className='footer-link-item'>FAQ</li>
<li className='footer-link-item'>Investor Relations</li>
<li className='footer-link-item'>Privacy</li>
<li className='footer-link-item'>Speed Test</li>
</ul>
</div>
</div>
)
}
export default Footer
I would appreciate any help of how to do this, either with the map() function or with CSS rules.
Thank you
One thing that could be beneficial is separating the concerns. Create a separate component that will handle one column at a time.
In my case, I created a Column component that returns a 'ul' JSX tag and display 'li' JSX tags based on linksToDisplay array received as props.
const Column = ({ linksToDisplay, key }) => (
<ul key={key} className='px-4'>
{linksToDisplay.map((item) => (
<li key={item.id}>{item.link}</li>
))}
</ul>
);
Then, I use my Column component inside my Footer component to display the columns based on a set criteria.
const Footer = () => {
return (
<div className='container mx-auto flex px-2 lg:px-5 py-24 h-screen
items-center justify-center flex-row'>
{links.map((link, index) => {
// So you get a new column after 4 items have been displayed
if (index % 4 === 0) {
// Array.slice to get the next 4 links in the array
const nextFourLinks = links.slice(index, index + 4);
return <Column key={link.id} linksToDisplay={nextFourLinks}
/>;
}
})}
</div>
);
};
After that, apply some styling to your elements and in my case I am using tailwindCSS and you should have your columns displaying the links.
Output:
For reference:
Array.prototype.slice()

Vuejs how to access nested object by keys concatenated with dot in a variable?

Suppose I have the following data:
var a = [{id: 1, name: {en: "English"}, desc: {en: "desc"}}];
Above array has more elements, suppose I have another component to create checkbox lists from an array, now I want to pass this array to that component with some other props like id key to use for id of my checkbox items, and label to use as the checkbox labels, The key I want to use as label for checkbox is name.en.
My data has the following format:
[{
"name": {
"en": "Limited Liability Company",
"dr": "",
"pa": ""
},
"description": {
"en": "This type of business combines the pass-through taxation benefits of a partnership with the limited-liability benefits of a corporation.",
"dr": "",
"pa": ""
},
"id": 1,
},
{
"name": {
"en": "Corporation",
"dr": "",
"pa": ""
},
"description": {
"en": "A corporation is a business in which a group of people acts together as a single entity; most commonly, owners of a corporation are shareholders who exchange consideration for the corporation's common stock. Incorporating a business releases owners of financial liability of business obligations; however, a corporation has unfavorable taxation rules for the owners of the business.",
"dr": "",
"pa": ""
},
"id": 2
}]
My checkbox component require 3 props id, label, data, following is my component html:
<div class="mb-3" v-for="(item, index) in listData" :key="index">
<div class="checkbox-wrapper d-flex">
<input type="checkbox" :id="item[id]" :value="item[id]" :checked="item.isChecked" #change="setValue($event, item)">
<label :for="item[id]" class="checkbox-label-over-flow"><span>{{item[label]}}</span></label>
</div>
</div>
Now how can I access label of each item with label variable ? if label = 'name.en'
I'm not sure how or when you are accessing the checkbox value, but the value is what you care about. Change the value to be your label.
<div class="mb-3" v-for="(item, index) in listData" :key="index">
<div class="checkbox-wrapper d-flex">
<input type="checkbox" :id="item.id" :value="item.label" :checked="item.isChecked" #change="setValue($event, item)">
<label :for="item[id]" class="checkbox-label-over-flow"><span>{{ item.label }}</span></label>
</div>
</div>
Also, #change, you are calling setValue() and passing item. You can access item.label from within the setValue() function as well

React search the text in an array of objects on Onchange of input

I am trying to manipulate a table data on the basis of the search in the table. So, what I have is this type of data:
this.props.datalist = {
"content": [{
"id": "5b7d4a566c5fd00507501051",
"companyId": null,
"title": "Senior/ Lead UI Developer",
"jobDescription": null,
"technology": "java"
},{
"id": "5b7d4a566c5fd005075011",
"companyId": null,
"title": "ead UI Developer",
"jobDescription": null,
"technology": "angular"
}]
}
In this I have this data coming from my `redux state. So I show this to user in the table form by passing this as a props.
I have a search field:
<input type="text"
id="searchJob"
className="form-control-sm border-0 flex-grow-1"
value={this.state.search}
placeholder="Company Name / Technology / Job title"
onChange={this.onInputChnage}
/>
<i className="fa fa-search search-job"></i>
onInputChnage = (e) => {
this.setState({
search: e.target.value
})
}
<div className="col-12 pr-0 pl-0">
<UserJobsTabel jobList={filteredList} />
</div>
</div>
Here , I got the filtered data in this array using filter
[{
"id": "5b7d4a566c5fd00507501051",
"companyId": null,
"title": "Senior/ Lead UI Developer",
"jobDescription": null,
"technology": "java"
},{
"id": "5b7d4a566c5fd005075011",
"companyId": null,
"title": "ead UI Developer",
"jobDescription": null,
"technology": "angular"
}]
Now, while setting state,
I am doing like this.
this.setState({ search: data })
If I want to set the state as with key like "content": [{}] like this then How can I do this ?
Because the way I am using it is like,
{this.props.dataList && this.props.dataList.content && this.props.dataList.content.length > 0 && this.props.dataList.content.sort((a, b) => b.createdAt - a.createdAt).map((item, key) => {
What I want to do is that the table data has two keys. One is title and Technolgoy now, search happens then it should check in the object and return the matched objects and that will be displayed on table.
Now if search has again nothing then it should show the default data that was present. Is there any way to do this?
The simplest way would be to create a variable in the render method containing the filtered props.datalist and use that for displaying.
something like
render(){
const { datalist:{content} } = this.props;
const { search } = this.state;
const filteredList = content.filter(job=>Object.values(job).some(value=>value.includes(search)));
return (<div>
//whatever
{filteredList.map(job=>....)}
</div>)
}
You could also do the filtering in the onInputChnage and store the filtered list in the local state.

Referencing information within arrays stored with an ObservableArray

Currently I am pulling information from two JSON files stored online. My goal is to display the information stored within these files in my app, using one for content and the other for attributes that can apply to the content, like background and font color.
My main issue is this:
I am trying to fill an ObservableArray with other arrays, and then reference the information stored within each of those within the XML file. A fairly simple idea, yes?
Content JSON
{
"content": [
{
"description": "If you’ve been dreaming about owning a customizable smartwatch, the modular watch that London-based Blocks promised is now available ...",
"image": "https:\/\/cdn3.vox-cdn.com\/thumbor\/mOV6mjP_AI50YsQDbQ81444XEB4=\/0x21:2520x1701\/1310x873\/cdn0.vox-cdn.com\/uploads\/chorus_image\/image\/49811865\/hero-bg_2x.0.0.jpg",
"created_utc": "1467036570",
"title": "The Blocks modular smartwatch can now be pre-ordered",
"type": "04",
"url": "http:\/\/www.theverge.com\/circuitbreaker\/2016\/6\/9\/11894152\/blocks-modular-smartwatch-pre-order"
},
{
"description": "At Lenovo TechWorld, we got a glimpse at the Moto Z's developer mod kit and how it can be used to make wacky and weird slip-on attachments.",
"image": "http://img.youtube.com/vi/A0YFmMEjXP0/mqdefault.jpg",
"created_utc": "1467032545",
"title": "Lenovo's Experimental Moto Mods",
"feedid": "03",
"url": "https://www.youtube.com/watch?v=A0YFmMEjXP0"
},
{
"description": "",
"image": "https://pbs.twimg.com/media/CkmZk8QXIAEKnTF.jpg",
"created_utc": "1467035885",
"title": "The US just approved six airlines to begin flying to Cuba",
"feedid": "02",
"url": "http://www.theverge.com/2016/6/10/11903034/us-cuba-airlines-american-southwest-frontier-jetblue"
},
{
"description": "'Texts from Hillary' photo raised questions about Clinton email habits at State Department",
"image": "https://cdn1.vox-cdn.com/thumbor/COJRCv7KVVwj3uO5qt1XHZ5F02Y=/0x82:3010x2089/1280x854/cdn0.vox-cdn.com/uploads/chorus_image/image/49821307/AP_16147060028688.0.0.jpg",
"created_utc": "1467036728",
"title": "The photo went viral enough to catch the eye of the State Department.",
"feedid": "01",
"url": "https://www.facebook.com/verge/posts/1116679778368364"
},
{
"description": "One of the benefits of being (somewhat) bilingual is you get double the internet content. I feel very blessed to be able to enjoy both American internet full of...",
"image": "https://cdn2.vox-cdn.com/thumbor/gM8KeNQUzto6fmdot7wfA_q9jSs=/0x0:3000x2000/1310x873/cdn0.vox-cdn.com/uploads/chorus_image/image/49820235/GettyImages-499350590.0.jpg",
"created_utc": "1467036669",
"title": "If you drop an ant from the top of the Empire State Building, will it die?",
"feedid": "04",
"url": "http://www.theverge.com/tldr/2016/6/10/11894028/ant-dropped-from-empire-state-building-science-experiment"
},
{
"description": "Tesla has denied that its cars suffer from suspension defects, suggesting that comments from the US National Highway Traffic Safety Administration (NHTSA) have been misinterpreted.",
"image": "https://cdn2.vox-cdn.com/thumbor/IAh-NZAZzH_AwdO2ubVMKlZkB2Y=/187x0:2212x1350/1310x873/cdn0.vox-cdn.com/uploads/chorus_image/image/49819011/model-s-photo-gallery-06.0.0.jpg",
"created_utc": "1467042890",
"title": "Tesla denies Model S suspension defects, chides journalist in blog post",
"feedid": "04",
"url": "http://www.theverge.com/circuitbreaker/2016/6/9/11894152/blocks-modular-smartwatch-pre-order"
}
]
}
Sources and Attributes JSON
{
"sources": [
{
"category":"news",
"subject":"technology",
"adsenabled":true,
"bannerimgsrc":"https://www.camplaurel.com/images/pagegraphics/home/l-header-bg.jpg",
"rowbgimgsrc":"https://www.camplaurel.com/images/pagegraphics/home/l-header-bg.jpg",
"titlebgcolor":"#ffffff",
"row2ndcolor":"#000000",
"rowtxtcolor":"#e22805",
"rowbgcolor":"#ffffff",
"iconsrc": "https://pbs.twimg.com/profile_images/615501837341466624/I4jVBBp-.jpg",
"id": 1,
"shortname": "verge",
"name": "The Verge"
},
{
"category":"news",
"subject":"leisure",
"adsenabled":true,
"bannerimgsrc":"https://pbs.twimg.com/profile_banners/275686563/1433249898/1500x500",
"rowbgimgsrc":"null",
"titlebgcolor":"#ece4d1",
"row2ndcolor":"#9b4e34",
"rowtxtcolor":"#6b2e1e",
"rowbgcolor":"#ece4d1",
"iconsrc": "https://camo.githubusercontent.com/b13830f5a9baecd3d83ef5cae4d5107d25cdbfbe/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f3732313033382f313732383830352f35336532613364382d363262352d313165332d383964312d3934376632373062646430332e706e67",
"id": 1,
"shortname": "Laurel South",
"name": "Camp Laurel South, Mains Premier Sleep Over Camp"
}
]
,
"feeds": [
{
"hidden": false,
"iconsrc": "http://icons.iconarchive.com/icons/danleech/simple/1024/facebook-icon.png",
"id": 1,
"notistat": "Sound and Text",
"sourceid":1,
"title": "The Verge Facebook"
},
{
"hidden": false,
"iconsrc": "http://icons.iconarchive.com/icons/danleech/simple/1024/facebook-icon.png",
"id": 2,
"notistat": "Sound and Text",
"sourceid":1,
"title": "The Verge Twitter"
},
{
"hidden": false,
"iconsrc": "http://icons.iconarchive.com/icons/danleech/simple/1024/facebook-icon.png",
"id": 3,
"notistat": "Sound and Text",
"sourceid": 1,
"title": "The Verge Youtube"
},
{
"hidden": false,
"iconsrc": "http://icons.iconarchive.com/icons/danleech/simple/1024/facebook-icon.png",
"id": 4,
"notistat": "Sound and Text",
"sourceid": 1,
"title": "The Verge RSS"
}
]
}
My JavaScript file uses a variable listed as bindingContext as the bindingContext of the page. myArray is a part of the bindingContext, and is being pushed into by my JSON mapping and loading functions, at least in theory.
var Observable = require('data/observable').Observable;
var ObservableArray = require('data/observable-array').ObservableArray;
var http = require("http");
var moment = require('moment');
var frameModule = require('ui/frame');
var bindingContext = new Observable({
title: "Loading...",
myArray: new ObservableArray()
});
function pageLoaded(args) {
var page = args.object;
page.bindingContext = bindingContext;
loadSources();
loadFeeds();
loadContent();
}
function loadContent() {
var content = [];
http.getJSON("http://www.doesntmatter.com/jsoncontent.php")
.then(function (r) {
bindingContext.title = 'Notifications Up to Date';
r.content.map( function(item) {
item.friendlyTime = moment(item.created_utc * 1000).fromNow();
content.push(item);
});
bindingContext.myArray.push(content);
console.log("content loaded.");
});
}
function loadSources() {
var mysources = [];
http.getJSON("http://www.secrets.com/jsonsource.php")
.then(function (r) {
r.sources.map( function(item) {
mysources.push(item);
console.log(item.name);
});
});
bindingContext.myArray.push(mysources);
console.log("sources loaded!");
};
}
//LoadSources should add all listed Sources into an array of sources, which is then pushed into the larger "myArray" which allows coloration and other css items to be determined for each object within an array
function loadFeeds() {
var myfeeds = [];
http.getJSON("http://www.shhhhhhhh.com/jsonsource.php")
.then(function (r) {
r.feeds.map( function(item) {
myfeeds.push(item);
});
bindingContext.myArray.push(myfeeds);
console.log("feeds loaded.");
});
}
//LoadFeeds should add all listed feeds into an array of feeds, which is also loaded into "myArray", which can then be drawn from to create individual color schemes
exports.pageLoaded = pageLoaded;
The part I am having a lot of trouble with is correctly referencing the array, subarrays, and contents of each within both the JavaScript file and the XML file due to a somewhat rusty knowledge of both languages.
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="pageLoaded">
<Page.actionBar>
<ActionBar title="Notify">
</ActionBar>
</Page.actionBar>
<ListView items="{{ myArray }}" itemTap="itemTap" loadMoreItems="loadMoreItems" class="containter">
<ListView.itemTemplate>
<GridLayout rows="21,*,*" columns="90,*" width="*" height="*" >
<!-- <Image row="0" col="0" colSpan="1" rowspan="3" src="{{ getItem[2].image }}" /> -->
<!-- <Label row="0" col="1" colSpan="1" class="time" text="{{ friendlyTime }}" textAlignment="right" /> -->
<!-- <Label row="1" col="1" colSpan="1" class="title" text="{{ content.title }}" margin="1" textWrap="true" /> -->
<!-- <Label row="2" col="1" colSpan="1" class="description" text="{{ description }}" textWrap="true" backgroundColor="{{ this is where I would want to reference the contents of the subarrays}}" /> -->
</GridLayout>
</ListView.itemTemplate>
</ListView>
</Page>
Again, just to reiterate: I have an ObservableArray which is part of the bindingContext of the page. This is being filled with other arrays, which are each filled with information I want to apply to my XML file. How can I reference this information using the correct syntax for both JavaScript and XML?
I think you actually need to rethink your design. ;-)
First issue that occurred to me is that myArray[0] can end up being content, sources or feeds. Just because you ran the code:
loadSources();
loadFeeds();
loadContent();
In a synchronous fashion, does not guarentee the result order; each one of those loads the file from a ASYNC source (i.e. in this case http); depending on which one of those ASYNC sources actually responds with its data first, it is which one will get put into your MyArray first. ;-)
Your second issue is that
<ListView items="{{ myArray }}"
Will only create three of your GridLayout templates; because their are only three myArray items (i.e the content, feeds, source) based on your data; I'm pretty sure you aren't just wanting to show three line items.
Now the question becomes do you need each item to link to a source to a feed, or do you just want to combine all three types and display each type of line item differently based on which type it it.

Categories