const arr = ['name', 'contact number']
const App = () => (
<div style={styles}>
Add {arr.split(',').map(o=>o)}
</div>
);
why this won't work? I want to print Add name & contact, but stuck at splitting it.
You're using 2 functions wrong:
split is supposed to be used to split a string into an array, around the provided character. You already have the resulting array.
.map(o=>o) is useless - it basically returns the same array provided.
You're probably looking to do this Add {arr.join(' & ')}.
You are looking to join the values
Add {arr.join(',')}
Below links should help you
MDN split
MDN join
There is nothing to split. I think you are trying to join them:
const arr = ['name', 'contact number']
const App = () => (
<div style={styles}>
Add {arr.join(',')}
</div>
);
Related
I have some divs that render this way:
<div class="customer-data-column">
<h3>Title:</h3>
<div>Name Lastname</div>
<div>123 Address xxx yyy</div>
<div>Chicago XY 33056</div>
<div>Country name</div>
</div>
This content is generated by:
{customerData.replaceAll("/r", "").split("\n").map(item => <div key={item}>{item}</div>)}
This data is coming from redux.
In console log (from redux data) the address appears this way:
Name Lastname\n123 Address xxx yyy\nChicago XY 33056\nCountry name
I want to check in Cypress if this address is correct, the same that is in redux.
I need some way that merges the content of the divs into one string, and adds the \n between each div.
I thought I could start this way:
cy.get('.customer-data-column').should($title => {
const store = Cypress.store.getState();
const reduxPath = store.customerData;
expect("not sure what to put here... how to merge").to.equals(reduxPath)
Can anyone please help?
===
EDIT
I made it almost work this way:
I added a class to the inner divs, so they render this way:
<div class="customer-data-column">
<h3>Title:</h3>
<div class="address-row">Name Lastname</div>
<div class="address-row">123 Address xxx yyy</div>
<div class="address-row">Chicago XY 33056</div>
<div class="address-row">Country name</div>
</div>
And the test:
cy.get('.address-row').then($divList => {
const textArray = Cypress.$.makeArray($divList).map(el => el.innerText)
const actual = textArray.join(textArray, '\n') // use join to array of strings into single string
expect(actual).to.eql(billToAddress)
})
However it still fails with such message:
assert expected Name LastnameName Lastname,23 Address xxx yyy,Chicago
XY 33056,Country name23 Address xxx yyyName Lastname,23 Address xxx
yyy,Chicago XY 33056,Country name7th FloorName Lastname,23 Address xxx
yyy,Chicago XY 33056,Country nameBrooklyn NY 11210Name Lastname,23
Address xxx yyy,Chicago XY 33056,Country nameCountry name to deeply
equal Name Lastname\n23 Address xxx yyy\n7th Floor\nBrooklyn NY
11210\nCountry name
Edit 2:
The solution that I found and works is this one:
.then(users => {
const billToAddress = users.response.body.filter(el => el.orderNumber === '3-331877')[0]
.billTo
cy.get('.address-row').each((item, index) => {
cy.log(cy.wrap(item).should('contain.text', billToAddress.split('\n')[index]))
})
})
Of course if somebody has a better way for achieving this test, I am open to learn more and code better.
If you make an array of the store data, an .each() loop can compare them.
const store = Cypress.store.getState()
const reduxData = store.customerData // expect 'Name Lastname\n123 Address xxx yyy\nChicago XY 33056\nCountry name'
const reduxDataArray = reduxData.split('\n')
cy.contains('.customer-data-column', 'Title:')
.find('div') // only divs inside '.customer-data-column'
.each(($div, index) => {
expect($div.text()).to.eq(reduxDataArray[index])
})
From other comment, it looks like cy.get('.custom-data-column') isn't strong enough to isolate this HTML you need to work on.
Perhaps cy.contains('.customer-data-column', 'Title:') is better.
All text at once
In this particular case you can test all text at once by globally removing \n
const store = Cypress.store.getState()
const reduxData = store.customerData // expect 'Name Lastname\n123 Address xxx yyy\nChicago XY 33056\nCountry name'
const reduxAllTexts = reduxData.replace(/\n/g, '')
cy.contains('.customer-data-column', 'Title:')
.find('div')
.invoke('text')
.should('eq', reduxAllTexts)
If the Cypress function yields multiple elements, we can join the text of those elements to create your string.
cy.get('.custom-data-column').find('div').then(($divList) => {
const store = Cypress.store.getState();
const reduxPath = store.customerData;
const textArray = $divList.map((x) => x.text()); // get the text values as an array
const actual = textArray.join(textArray, '\n'); // use join to array of strings into single string
expect(actual).to.eql(reduxPath);
});
This is probably simple but I am having some difficulty. I am trying to return a specific class name from an element as a string. There will be many interactive_items with different class name that follow the element__content__item pattern so I need the element__content__item class name.
Right now I am just trying the first element found.
I need to get the string slider__content__item
const elements = [...document.querySelectorAll('.interactive__item')]
const regex = new RegExp(/^.*(content__item).*$/g)
const result = elements[0].className.match(regex).toString()
This returns slider__content__item interactive__item entry which is correct but then how do I pull out the slider__content__item class as a string.
If there is a better way to do this I am all ears.
<aside class="slider__content__item interactive__item entry">
</aside>
/\w+__content__item/g
const elements = [...document.querySelectorAll('.interactive__item')]
const regex = new RegExp(/\w+__content__item/g)
const result = elements[0].className.match(regex).toString()
console.log(result)
<aside class="slider__content__item interactive__item entry">
</aside>
const elements = Array.from(document.querySelectorAll('.interactive__item'));
const regex = new RegExp(/^.*(content__item).*$/g)
const result = Array.from(elements[0].classList); // you have all item classes after that write your mathing statements
maybe try with document.getElementById(id of the element).className
or document.getElementByTagName(name of the tag).className ?
Currently, I have a huge JavaScript array where each element is like this:
[{"open":235.86,
"high":247.13,
"low":231.5,
"close":244.1,
"volume":55025735,
"date":"2019-05-01T21:00:00.000Z"}
...
I need to remove everything except the price after high. What is the most efficient way I can do this?
I've tried popping the individual elements, but I can't help but feel as if there is a more efficient/easier way to do this.
So hopefully the ending array would just be [235.86].
The below code should work. It's efficient enough :D
for (i in arrayName){
// Loops through array
delete arrayName[i].high
delete arrayName[i].low
delete arrayName[i].close
delete arrayName[i].volume
delete arrayName[i].date
// Deletes unwanted properties
}
console.log(arrayName)
// Print output
One potential solution would be to map the array to a new array like so:
const yourArray = [
{"open":235.86, "high":247.13, "low":231.5, "close":244.1, "volume":55025735},
{"open":257.52, "high":234.53, "low":220.2, "close":274.1, "volume":23534060},
]
const mappedArray = yourArray.map(el => el.open);
// mappedArray = [235.86, 257.52]
Check out the MDN documentation for the map method, Array.prototype.map()
Note: The above example uses ECMAScript 6 arrow functions and implicit returns. It is functionally equivalent to:
const yourArray = [
{"open":235.86, "high":247.13, "low":231.5, "close":244.1, "volume":55025735},
{"open":257.52, "high":234.53, "low":220.2, "close":274.1, "volume":23534060},
]
const mappedArray = yourArray.map(function(el){
return el.open
});
You can use reduce for this scenario. Example
var temp = [{"open":235.86, "high":247.13, "low":231.5, "close":244.1, "volume":55025735, "date":"2019-05-01T21:00:00.000Z"}];
var highValArray = temp.reduce((arr, t) => {
return arr.concat(t['high']);
}, []);
You can learn more about reduce function at the MDN website.
This should work:
your_array.map((item) => {
return item.high
})
I am developing angular blockchain application using hyperledger composer tool.When i query the historian i got a response like in the below.
{
transactionType:"org.hyperledger.composer.system.AddParticipant"
}
I display the transaction type using follwing code snippet.
<div class="col-md-6">
{{participant.transactionType}}
</div>
The displayed part like this.
org.hyperledger.composer.system.AddParticipant
but I only want to display the 'AddParticipant' part in the response without 'org.hyperledger.composer.system.' part. How can I fix it?
For that just do little string manipulation. Make use of JS .split() method which splits string by argument character/string.
let arr = this.participant.transactionType.split(".");
then arr[arr.length-1] is your required string part which you can bind to view. Like use below {{txTyepe}} in template binding
this.txType = arr[arr.length-1];
you can use "substr" to pick a word from string but you need position of your word in your string first so :
const str = 'org.hyperledger.composer.system.AddParticipant'
let getPosition = str.indexOf('AddParticipant'); // get the position of AddParticipant
let getWord = str.substr(getPosition,13);
the length of AddParticipant is 13 also you can change the code above for better and cleaner and multi use code
const splitWord = (index)=>{
const str = 'org.hyperledger.composer.system.AddParticipant'
let strArray = str.split('.')
let getPosition = str.indexOf('AddParticipant'); // get the position of AddParticipant
let getWord = str.substr(getPosition,strArray[index].lenght); //you just need to change the number
return getWord;
}
console.log(splitWord(4));
You can also get the last "word" with regular expression :
<div class="col-md-6">
{{participant.transactionType.match(/\w+$/i)}}
</div>
When you see your historian data it'll look something like this
'$namespace': 'org.hyperledger.composer.system',
'$type': 'HistorianRecord',
'$identifier': '6e43b959c39bdd0c15fe45587a8dc866f1fa854d9fea8498536e84b45e281b31',
'$validator': ResourceValidator { options: {} },
transactionId: '6e43b959c39bdd0c15fe45587a8dc866f1fa854d9fea8498536e84b45e281b31',
transactionType: 'org.hyperledger.composer.system.IssueIdentity',
transactionInvoked:
Relationship {
'$modelManager': [Object],
'$classDeclaration': [Object],
'$namespace': 'org.hyperledger.composer.system',
'$type': 'IssueIdentity',
'$identifier': '6e43b959c39bdd0c15fe45587a8dc866f1fa854d9fea8498536e84b45e281b31',
'$class': 'Relationship' },
So, instead of taking transactionType you can use the transactionInvoked object. And then you can get whatever information you want from that object.
Finally your code should be like this
<div class="col-md-6">
{{participant.transactionInvoked.$type}}
</div>
In my case it will give me transaction type as just 'IssueIdentity'.
I'm currently using Ramda to output a Material-UI CheckCircle for every instance of a perk a record has. They can have a maximum of 18, so I am also using it to keep counting past the perk to a max of 18 to show the potential maximum.
{R.range(0, this.props.perkProgress).map(() => <CheckCircle key={uid()} /> )}
{R.range(this.props.perkProgress, 18).map(() => <CheckBoxOutline key={uid()} /> )}
These two lines work perfectly, however I need to also interject something after every 'third' one - Rather it's a box, or a checkmark. Since I don't believe I can do with Ramda, how could I write this in a normal JS sense (Or wrap this inside of a function; either one) to get the output I need?
this.props.perkProgress is always an integer between 0 and 18.
If they have '5', I would expect 5 checkmarks, and 13 empty squares.
Adding a terrible drawing of the currently functioning section, and the desired endresult :
This can be achieved using Ramda by first splitting the list of elements using R.splitEvery then adding the separator between each split list using R.intersperse and finally joining the split lists back together with R.unnest.
(n.b. I've swapped out your JSX with strings below for the sake of brevity)
// inserts `sep` between every `n` elements of a list `xs`
const separateEvery = (sep, n, xs) =>
R.unnest(R.intersperse([sep], R.splitEvery(n, xs)))
const genElements = (totalSize, progress) =>
separateEvery('Separator', 3, R.concat(
R.repeat('CheckCircle', progress),
R.repeat('CheckBoxOutline', totalSize - progress)
))
console.log(genElements(18, 7))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
updates in response to comments below
One approach to adding a key to each of the generated elements would be to map over each with React.cloneElement.
const genElementsWithKey = R.pipe(
genElements,
R.addIndex(R.map)((el, key) => React.cloneElement(el, {key}))
)
Alternatively, if you didn't want to use cloneElement for some reason then you could swap out R.intersperse using R.zipWith to create a unique separator element to insert between each group of elements.
const createCircle = _ => '<CheckCircle key={uid()} />'
const createCheckBox = _ => '<CheckBoxOutline key={uid()} />'
const createSeparator = _ => '<Separator key={uid()} />'
const genElements = (totalSize, progress) => {
const splitEls = R.splitEvery(3, R.concat(
R.map(createCircle, R.range(0, progress)),
R.map(createCheckBox, R.range(progress, totalSize))
))
const firstSplitGroup = splitEls[0]
const remainingSplitGroups = R.tail(splitEls)
// create a list of separators matching the number of elements in remainingSplitGroups
const separators = R.map(createSeparator, R.range(0, remainingSplitGroups.length))
return R.concat(
// keep the first split group as is
firstSplitGroup,
// prepend a separator to each of the remaining split groups
R.unnest(R.zipWith(R.prepend, separators, remainingSplitGroups))
)
}
console.log(genElements(18, 7))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>