ForkJoin() issue on Angular - javascript

Hello I am currently working on an UI and I need to print for each 'digId' a value that I retrieved in an unique JSON response.
In the case below, I have 3 incidents and I did a fork to have access to the 3 JSON response.
digId='4149';
digId2='4719';
digId3='4309';
ngOnInit(): void {
const parallel$ = Observable.forkJoin(
this.http.get('http://ninjaopsapi?tablename=REF_OPS_ALARM&babylonref=' + this.digId),
this.http.get('http://ninjaopsapi?tablename=REF_OPS_ALARM&babylonref=' + this.digId2),
this.http.get('http://ninjaopsapi?tablename=REF_OPS_ALARM&babylonref=' + this.digId3)
);
parallel$.subscribe( data => {
this.alarms = data, console.log(data);
})
}
My goal is to print the element circled in blue for example: Capture
But with this code below in my html, I retrieve the element [0] for the three incidents and I can't put an additionnal [0] to select only one.
<div *ngFor= "let alarm of alarms">
<div [(ngModel)]="digId" ngDefaultControl>
<div>{{alarm[0].alertMessage}}</div>
</div>
</div>
Is it possible to print the first element of the first element in an array when the .subscribe is done with a "forkJoin()" ?
Thank you
UPDATE
I only changed {{alarm[0][0].alertMessage}} by {{alarms[0][0].alertMessage}} and delete the loop *ngFor="let alarm of alarms
and it works well ! Thank you

You could simply do
parallel$.subscribe( data => {
this.alarms = data.map(x => x[0]);
});
<div>{{alarm.alertMessage}}</div>

Related

React.js - Done a API fetch that renders all items, now I want to be able to route on each item to their "own" page with JSON info

I have created an React site that renders all items inside an API Fetch on a page. What I want now is to be able to press each item that renders and be able to get routed to a new component that shows "more" info about that item.
Below I have the following code that takes in the "input" that you can use to search for all items or for a specific item.
const AgentSearch = (e) => {
e.preventDefault();
function capitalizeName(input) {
return input.replace(/\b(\w)/g, (s) => s.toUpperCase());
}
console.log('you hit search', input);
dispatch({
type: actionTypes.SET_SEARCH_TERM,
term: capitalizeName(input),
});
//do something with input
history.push('/findagent');
};
return (
<form className='search'>
<div class='search__input'>
<SearchIcon className='search__inputIcon' />
<input value={input} onChange={(e) => setInput(e.target.value)} />
</div>
Here is the code that renders all items:
eachName = data.map((item) => {
return (
<tr>
<td class='text-left'>{item.name}</td>
<td class='text-left'>{item.agency}</td>
</tr>
);
});
Basically what I would like to do is to "catch" the {item.name} and put that into a new query into the fetch once you press that item on the list that got created.
I tried to create a button that covers the whole class and then put {item.name} as input, but that does not work, also tried to make a "fake" input window that has the {item-name} stored for each item on list, even though the {item-name} gets onto the input window, once i push the button that its connected to, it says it doesn't have any value.
Does anyone know of any clean idea for this? I'm new to React so this might be really easy, haha.
Thanks!
The simplest way is to do onCLick on the td. See the code below.
const eachName = data.map((item) => {
return (
<tr>
<td class='text-left' onClick={() => handleNameClick(item.name)}>{item.name}</td>
<td class='text-left'>{item.agency}</td>
</tr>
);
});
You can define the handleNameClick function. You'll get the item.name as the parameter. See below.
const handleNameClick = itemName => {
//your code to send request for the clicked name
}

Saving Values to Backend from TextBoxes using React Flux Pattern

I have several text boxes and a save button
Each text box value is loaded using the following approach
{
this.getElement('test3lowerrangethreshold', 'iaSampling.iaGlobalConfiguration.test3lowerrangethreshold',
enums.IASamplingGlobalParameters.ModerationTest3LowerThreshold)
}
private getElement(elementid: string, label: string, globalparameter: enums.IASamplingGlobalParameters): JSX.Element {
let globalParameterElement =
<div className='row setting-field-row' id={elementid}><
span className='label'>{localeHelper.translate(label)}</span>
<div className="input-wrapper small">
<input className='input-field' placeholder='text' value={this.globalparameterhelper.getDataCellContent(globalparameter, this.state.globalParameterData)} />
</div>
</div>;
return globalParameterElement;
}
Helper Class
class IAGlobalParametesrHelper {
public getDataCellContent = (globalparameter: enums.IASamplingGlobalParameters, configdata: Immutable.List<ConfigurationConstant>) => {
return configdata?.find(x => x.key === globalparameter)?.value;
}
}
This works fine. Now the user is allowed to update these text values.And on click of save the changes should be reflected by calling a web api .
I have added an onlick event like this
<a href='#' className='button primary default-size' onClick={this.saveGlobalParameterData}>Save</a>
Now inorder to save the data i need a way to identify the text element which has changed.For that i have added an update method within the Helper class
public updateCellValue = (globalparameter: enums.IASamplingGlobalParameters, configdata: Immutable.List<ConfigurationConstant>,updatedvalue:string) => {
let itemIndex = configdata.findIndex(x => x.key === globalparameter);
configdata[itemIndex] = updatedvalue;
return configdata;
}
and return the updated configdata ,and i plan to call this method in the onchange event of every text box like this
<input className='input-field' placeholder='text' onchange={this.setState({ globalParameterData: this.globalparameterhelper.updateCellValue(globalparameter, this.state.globalParameterData, (document.getElementById(elementid) as HTMLInputElement).value})}
But this does not seem like a correct approach as there are number of syntactical errors. I initially got the data using an actioncreator like this.Please advice.
samplingModerationActionCreator.getGlobalParameters();
samplingModerationStore.instance.addListener(samplingModerationStore.SamplingModerationStore
.IA_GLOBAL_PARAMETER_DATA_GET_EVENT,
this.getGlobalParameterData);
}

How to fetch the value of an attribute of an element in cypress?

I am working on cypress testing for a table in a web page. An example of the elements in the page is as follows:
<div class="MuiDataGrid-cell MuiDataGrid-cellWithRenderer" data-testid="admission-row">
<div class="MuiDataGrid-cell" role="cell" data-value="2020-11-21" data-field="admissionDate" data-rowindex="0">21-NOV-2020</div>
<div class="MuiDataGrid-cell" role="cell" data-value="2020-10-15" data-field="admissionDate" data-rowindex="0">15-OCT-2020</div>
<div class="MuiDataGrid-cell" role="cell" data-value="2020-09-07" data-field="admissionDate" data-rowindex="0">07-SEP-2020</div>
</div>
In the test that I am working on, I want to get the data-value attributes from each of the div elements and store them in a list, this is what I am trying.
let dateList = [];
cy.get("[data-testid='admission-row']").children().each((element) => {
cy.get(element).invoke("data-value").then((date) => {
dateList.push(date);
});
});
However, this is not working and I am facing an error data-value does not exist in your subject. I have also tried with cy.its instead of cy.invoke that failed as well. Any help regarding this bit of code would be incredibly helpful.
Based on #Hiram comments, the code which worked is as follows:
let dateList = [];
cy.get("[data-testid='admission-row']").children().each((element) => {
cy.get(element).invoke("attr", "data-value").then((date) => {
dateList.push(date);
});
});
You have to use .invoke('attr', 'data-value') instead of .invoke('data-value'). Reference from Cypress Docs.
let dateList = [];
cy.get("[data-testid='admission-row']").children().each((element) => {
cy.wrap(element).invoke('attr', 'data-value').then((date) => {
dateList.push(date);
});
});

How to display the content of an array inside an object in Reactjs

I have a React component. When the user makes a form selection, it retrieves the following object (the content of the object varies depending on the selection made):
Data
jsonObj={
"name":"main",
"type":"meat",
"values":[
["chicken","Roast chicken with vegetables"],
["beef","Beef and Yorkshire pudding"]
]}
Desired results
Here's what I want to display on screen when rendered:
<div>
<label htmlFor="chicken">Roast chicken and vegetables</label>
</div>
<div>
<label htmlFor="beef">Beef and Yorkshire pudding</label>
</div>
My failed attempt!
Object.entries(jsonObj["values"]).map(([val,index]))=>{
return(
<div>
<label htmlFor={val[index][0]}>{jsonSub[key][1]}:</label>
</div>
)
}
The result of this is:
Cannot read property '0' of undefined.
And when I try it in the browser console I get "Uncaught SyntaxError: Malformed arrow function parameter list". Is anyone able to help me get my desired results?!
Many thanks!
Katie
Object.entries method is meant to get array from object, But your "values" is already array, So directly use the map
jsonObj["values"].map(([html, text]) => (
<div>
<label htmlFor={html}>{text}</label>
</div>
));
You don't really need Object.entries(). Simply using .map() on jsonObj.values and accessing on each iteration the current array of elements and showing up e[0] and e[1] for <label>.
Instead you can do it easier like the following:
jsonObj.values.map(e => {
return <div>
<label htmlFor={e[0]}>{e[1]}</label>
</div>
});
See the following example:
const jsonObj = {
"name":"main",
"type":"meat",
"values":[
["chicken","Roast chicken with vegetables"],
["beef","Beef and Yorkshire pudding"]
]}
const result = jsonObj.values.map(e => {
// just returning a template literal for representation
return `<label htmlFor="${e[0]}">${e[1]}</label>`;
});
console.log(result)
I hope this helps!

AngularJS - Get printed value from scope inside an attribute?

I'm currently working on an AngularJS project and I got stuck in this specific requirement.
We have a service that has all the data, DataFactoryService. Then, I have a controller called DataFactoryController that is making the magic and then plot it in the view.
<div ng-repeat = "list in collection">
{{list.name}}
...
</div>
Now, we have a requirement that pass multiple data into one element. I thought an "ng-repeat" would do, but we need to have it inside an element attribute.
The scenarios are:
At one of the pages, we have multiple lists with multiple data.
Each data has a unique code or ID that should be passed when we do an execution or button click.
There are instances that we're passing multiple data.
Something like this (if we have 3 items in a list or lists, so we're passing the 3 item codes of the list):
<a href = "#" class = "btn btn-primary" data-factory = "code1;code2;code3;">
Submit
</a>
<a href = "#" class = "btn btn-default" data-factory = "code1;code2;code3;">
Cancel
</a>
In the example above, code1,code2,code3 came from the list data. I tried several approach like "ng-repeat", "angular.each", array, "ng-model" but I got no success.
From all I've tried, I knew that "ng-model" is the most possible way to resolve my problem but I didn't know where to start. the code below didn't work though.
<span ng-model = "dataFactorySet.code">{{list.code}}</span>
{{dataFactorySet.code}}
The data is coming from the service, then being called in the controller, and being plot on the HTML page.
// Controller
$scope.list = dataFactoryService.getAllServices();
The data on the list are being loaded upon initialization and hoping to have the data tags initialized as well together with the list data.
The unique code(s) is/are part of the $scope.list.
// Sample JSON structure
[
{ // list level
name: 'My Docs',
debug: false,
contents: [ // list contents level
{
code: 'AHDV3128',
text: 'Directory of documents',
...
},
{
code: 'AHDV3155',
text: 'Directory of pictures',
...
},
],
....
},
{ // list level
name: 'My Features',
debug: false,
contents: [ // list contents level
{
code: 'AHGE5161',
text: 'Directory of documents',
...
},
{
code: 'AHGE1727',
text: 'Directory of pictures',
...
},
],
....
}
]
How can I do this?
PLUNKER -> http://plnkr.co/edit/Hb6bNi7hHbcFa9RtoaMU?p=preview
The solution for this particular problem could be writing 2 functions which will return the baseId and code with respect to the list in loop.
I would suggest to do it like below
Submit
Cancel
//inside your controller write the methods -
$scope.getDataFactory = function(list){
var factory = list.map( (a) => a.code );
factory = factory.join(";");
return factory;
}
$scope.getDataBase= function(list){
var base= list.map( (a) => a.baseId);
base= base.join(";");
return base;
}
Let me know if you see any issue in doing this. This will definitely solve your problem.
You don't really have to pass multiple data from UI if you are using Angular.
Two-way data binding is like blessing which is provided by Angular.
check your updated plunker here [http://plnkr.co/edit/mTzAIiMmiVzQfSkHGgoU?p=preview]1
What I have done here :
I assumed that there must be some unique id (I added Id in the list) in the list.
Pass that Id on click (ng-click) of Submit button.
You already have list in your controller and got the Id which item has been clicked, so you can easily fetch all the data of that Id from the list.
Hope this will help you... cheers.
So basing from Ashvin777's post. I came up with this solution in the Controller.
$scope.getFactoryData = function(list) {
var listData = list.contents;
listData = listData.map(function(i,j) {
return i.code;
});
return listData.join(';');
}

Categories