How to split Json response and get specific part using angular - javascript

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'.

Related

Cypress get content of several DIVs, and compose one long string

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);
});

ReactIntl.FormattedPlural Component to String

I am new to React.
I used ReactIntl.FormattedPlural to format the plural.
<FormattedPlural
value={10}
one='message'
other='messages'
/>
It works when I place this component in the render() function. However, I have a scenario that I want to get the String and passed into a function.
Instead of Using {value ==1 ? 'message' : 'messages'}, can I use ReactIntl.FormattedPlural to achieve this?
In any case, in the end you need to put it into the render.
Because the FormattedPlural is a component. To display it, you need to render it. It's how React works.
You can save it as variable:
const text = (<FormattedPlural value={10} one='message' other='messages' />)
For example if you have a condition and need to decide which string to render.
But in the end, the text should passed to the render to be displayed for user.
Derived from FormattedPlural implementation:
const { formatPlural } = useIntl()
// get the plural category ("one" or "other")
const pluralCategory = formatPlural(count);
const options = {
one: "message",
other: "messages",
}
const plural = options[pluralCategory as 'one'] || options.other;
See also: https://formatjs.io/docs/react-intl/api/#formatplural

Regex using array.filter in javascript

I'm trying to use a regular expression to filter the name column in a csv file that has be put into an object array. Everything works fine if I type the exact value.
values I want "king" to match are below:
kingkong, king kong, king-kong, king_kong, king11, kongking, kong-king, kong_king, kong king, 11king
I've tried using filter and find methods but I want to use filter to return multiple values if they exist. I have tried the following regex but can't figure out the proper sytax if it is even correct.
const CSVToJSON = require('csvtojson');
const user = "king";
CSVToJSON().fromFile("./locations.csv").then(source => {
var found = source.filter(function(v, i){
return ((v["name"]== /\bking.*/g));
})
You can use the following approach.
const CSVToJSON = require('csvtojson');
CSVToJSON().fromFile("./locations.csv").then(source => {
var found = source.filter(function(v, i){
return ((v["name"].match(/king/g)));
});
return statement could be something like
return ((/king/g).test(v["name"]));
OR
return ((v["name"].match(/king/g)));
Both should work
However, your sample patterns show that king might stand either at the beginning or at the end of the target (bot can't have both prefix and suffix). If I am right, that means you don't need regex for that.
const CSVToJSON = require('csvtojson');
const user = "king";
CSVToJSON().fromFile("./locations.csv").then(source => {
var found = source.filter((v, i) => v.startsWith(user) || v.endsWith(user))
/*rest of the code */
});
If king can stand anywhere, you can simply use includes instead.
This is what worked, I'm totally new to JavaScript:
const user = args;
var regex = new RegExp(user, "g");
CSVToJSON().fromFile("./locations.csv").then(source => {
var found = source.filter(function(v, i){
return ((v["name"].match(regex)));
})

using split and map in jsx

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>
);

Prettify json data in textarea input

I've searched for this particular topic and couldn't find anything similar to it. If there is please close this and give a link.
I'm creating a json data api simulator. I want users to be able to copy and paste a json object request into a textarea where they can also modify it before sending it to the server.
Problem is json obj copy and patses often results in extra spaces and is never aligned properly, even with the pre tag. I also want a good color scheme applied to keys and values.
I've seen plugins, other questions and snippets of code, but they don't apply to textareas where the text is editable. Is there to keep it styled while in edit mode without it showing all the html tags that styled it? I want to be able to write it from scratch with javascript or jquery.
The syntax highlighting is tough but check out this fiddle for pretty printing a json object entered in a text area. Do note that the JSON has to be valid for this to work. (Use the dev console to catch errors.) Check jsLint for valid json.
The HTML:
<textarea id="myTextArea" cols=50 rows=10></textarea>
<button onclick="prettyPrint()">Pretty Print</button>
The js:
function prettyPrint() {
var ugly = document.getElementById('myTextArea').value;
var obj = JSON.parse(ugly);
var pretty = JSON.stringify(obj, undefined, 4);
document.getElementById('myTextArea').value = pretty;
}
First try simple input like: {"a":"hello","b":123}
Simple pretty printing of JSON can be done rather easily. Try this js code: (jsFiddle here)
// arbitrary js object:
var myJsObj = {a:'foo', 'b':'bar', c:[false,2,null, 'null']};
// using JSON.stringify pretty print capability:
var str = JSON.stringify(myJsObj, undefined, 4);
// display pretty printed object in text area:
document.getElementById('myTextArea').innerHTML = str;
For this HTML:
<textarea id="myTextArea" cols=50 rows=25></textarea>
And check out JSON.stringify documentation.
Late answer but modern one, use the secret intendation parameter.
I usually go for:
JSON.stringify(myData, null, 4);
Here's the code definition, it explains it well.
stringify(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
/**
* Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
* #param value A JavaScript value, usually an object or array, to be converted.
* #param replacer An array of strings and numbers that acts as a approved list for selecting the object properties that will be stringified.
* #param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
*/
For the parsing step you're just going to want to JSON.parse the contents of the textarea and handle any errors from bad input.
For the formatting part of your question, Use JSON.stringify(blob, undefined, 2). Alternatively, if you need colors here is a simple JSON format/color component written in React:
const HighlightedJSON = ({ json }: Object) => {
const highlightedJSON = jsonObj =>
Object.keys(jsonObj).map(key => {
const value = jsonObj[key];
let valueType = typeof value;
const isSimpleValue =
["string", "number", "boolean"].includes(valueType) || !value;
if (isSimpleValue && valueType === "object") {
valueType = "null";
}
return (
<div key={key} className="line">
<span className="key">{key}:</span>
{isSimpleValue ? (
<span className={valueType}>{`${value}`}</span>
) : (
highlightedJSON(value)
)}
</div>
);
});
return <div className="json">{highlightedJSON(json)}</div>;
};
See it working in this CodePen:
https://codepen.io/benshope/pen/BxVpjo
Hope that helps!
If you are a jquery fan, you can also use this small plugin I wrote:
// The plugin
$.fn.json_beautify= function() {
this.each(function(){
var el = $(this),
obj = JSON.parse(el.val()),
pretty = JSON.stringify(obj, undefined, 4);
el.val(pretty);
});
};
// Then use it like this on any textarea
$('textarea').json_beautify();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea id="myTextArea" cols=50 rows=5>{"name":"John","age":30}</textarea>
<textarea id="myTextArea2" cols=50 rows=5>{"name":"Bob","age":55}</textarea>
UPD
Changed code to multiselected elements.
I don't think that can be done with regular textareas. What you can do (and how most online code editors do it) is to create a transparent textarea that overlays on top of a div that contains the styled code. The user would still be able to type and interact with the input (and it fires the associated form events), and you can show syntax highlighting in the div that the user will visually see
(see Textarea that can do syntax highlighting on the fly?)
Now as for JSON formatting, I would add custom events to the textarea so that when a user types or paste something, run it through a Javascript JSON prettifier (see How can I pretty-print JSON using JavaScript?) and then re-populate the div and textarea accordingly
Here's a recursive function to return an object if it has been stringified multiple times:
const jsonPrettify = (json) => {
if (typeof json === 'object' && json !== null) {
const pretty = JSON.stringify(json, undefined, 4);
return pretty;
}
try {
const obj = JSON.parse(json);
return jsonPrettify(obj);
} catch (e) {
return json;
}
};

Categories

Resources