Icon color shows same for all the icons in child component ionic4 - ionic4

I am using ionic 4 and i have a very strange issue. i have created a child components called social icons which is used to like or unlike ..etc. This child component will be called from parent component as shown below.
PARENT COMPONENT
<ion-card *ngFor="let creative of getArray">
<ion-card-header>
<social-icons [coll]="creative" (iconClicked)="updateUserReaction($event,creative?.id)"></social-icons><br>
</ion-card-header>
</ion-card>
Here i am calling child component within ngFor . Also i am passing creative obj to the child component.
creative obj :
{firstname: "Murali", description: "Photography of cute", nooflikes: 0, type: "creative", lastname: "Techwedge", …}
description: "Photography of cute"
elasticSearch_id: "creative_50"
file_type: "jpg"
filepath: "/documents/assets/Images/creative/IMG-20190310-WA0001_50.jpg"
firstname: "Murali"
id: 50
lastname: "Techwedge"
name: "Photography of cute"
noofcomments: 0
nooflikes: 0
noofshares: 0
noofunlikes: 2
resource_name: "IMG-20190310-WA0001_50.jpg"
socialIcons: Array(5)
0: {icon: "thumbs-up", operation: "cancellike", color: "danger"}
1: {icon: "thumbs-down", operation: "unlike"}
2: {icon: "eye", operation: "views"}
3: {icon: "text", operation: "comment"}
4: {icon: "settings", operation: "filter"}
length: 5
__proto__: Array(0)
timestamp: null
type: "creative"
user_id: 6
user_reaction: []
userobj: {id: 6, firstname: "Nikhil", lastname: "n", emailid: "nikhil#temp.org", password: "pass123", …}
views: 17
This is what creative obj data will be.
child component:
<ion-fab bottom>
<ion-grid>
<ion-row>
<ion-col size="2" *ngFor="let icon of coll?.socialIcons" >
<ion-card-title >
<ion-icon [color]="icon?.color" *ngIf="icon.icon != 'text' && icon.icon != 'settings'" [name]="icon.icon" (click)="clickedIcon(icon.operation)" style="font-size: 20px;"></ion-icon>
<ion-icon (click)="navigate()" *ngIf="icon.icon == 'text'" [name]="icon.icon" style="font-size: 20px;"></ion-icon>
<ion-icon *ngIf="icon.icon == 'settings'" [name]="icon.icon" style="font-size: 20px;" [routerLink]="['/filters/sharewith',{'id':coll?.id}]"></ion-icon>
</ion-card-title>
<ion-card-subtitle>
{{icon.value}}
</ion-card-subtitle>
</ion-col>
</ion-row>
</ion-grid>
</ion-fab>
Here in child component i am passing the color aattributes.
Below is the component.ts for child component.
ngOnInit() {
return new Promise((resolve, reject) => {
this.creativeServices.getCreativeReactions1(this.coll["id"],this.coll["userobj"]["id"]).pipe(map(res1=>res1.json())).subscribe(res1=>{
this.coll["user_reaction"] = res1;
this.coll["user_reaction"].map(element=>{
switch(element["latestReaction"]){
case 'like' :{
this.coll["socialIcons"][0]["color"] = "danger"
this.coll["socialIcons"][0]["operation"] = "cancellike"
break;
}
case "unlike":{
this.coll["socialIcons"][1]["color"] = "danger"
this.coll["socialIcons"][1]["operation"] = "cancelunlike"
break;
}
case "cancellike":{
this.coll["socialIcons"][0]["color"] = "default"
this.coll["socialIcons"][0]["operation"] = "like"
break;
}
case "cancelunlike":{
this.coll["socialIcons"][1]["color"] = "default"
this.coll["socialIcons"][1]["operation"] = "unlike"
break;
}
default:{
this.coll["socialIcons"][0]["color"] = "default"
}
}
})
resolve(this.coll)
console.log(this.coll)
})
})
// this.setTitle();
}
As you can see i am making a service call based on the response i get from the service call i am setting the color of icons for each creative object sent from parent component.
ISSUE : Suppose say if there is any value obtained from the response then the color of the icons changes for all the creatives irrespective of the switch condition.
say for a creative if the response from the service call is null then the color will be black.
now for second creative response exists based on the switch conditions the appropriate color is changed to this creative which is fine. But along with this the first creative color also gets changed. i,e this.coll.socialIcons arrays gets updated to all the creative objects.
I guess there is some issue with the way of rendering socialIcons.
Please let me know where am i going wrong?

This bit doesn't seem right:
case 'like' :{
this.coll["socialIcons"][0]["color"] = "danger"
this.coll["socialIcons"][0]["operation"] = "cancellike"
break;
}
case "unlike":{
this.coll["socialIcons"][1]["color"] = "danger"
this.coll["socialIcons"][1]["operation"] = "cancelunlike"
break;
}
case "cancellike":{
this.coll["socialIcons"][0]["color"] = "default"
this.coll["socialIcons"][0]["operation"] = "like"
break;
}
case "cancelunlike":{
this.coll["socialIcons"][1]["color"] = "default"
this.coll["socialIcons"][1]["operation"] = "unlike"
break;
}
default:{
this.coll["socialIcons"][0]["color"] = "default"
}
It's not clear what you're trying to do but whatever it is, you are only setting either ["socialIcons"][0] or ["socialIcons"][1] in all instances.
Problems with the question
You have not asked your question in a clear way, you should try to recreate an example with only the problem presented, and also give us all the information.
You are talking about user_reaction which has latestReaction in your code but when you posted a data sample user_reaction is just [].
If you are trying to run the code against an [] then its going to set the default case every time as its going to get undefined back from each switch test.

Related

trying to get an objects key which is a 'letters + counter number' variable but it won't work

I know tis might be a silly problem but I'm not sure how to frame this line of code to do what I need. I'm using Vue CLI and I have a some objects within an array in my data. one of those objects have several image links with key that goes -> img1 : ./link, img2: ./link2. In my function i need to change the target elements source to the next image i.e from img1 to img2 where I have a counter that stores the number that i want img to change to. however the results only show NaN.
here is my some HTML:
<img #click="storyboard" v-else :src="slide.img1" />
<div class="counter hide">
<p>{{ counter }} / 5</p>
</div>
here is some JS
data() {
return {
slides: [
{ title: 'Landing Page', img1: require("../assets/wadah/proposal.mp4"), info: "Wadah Archive is an alternative museum where everyday artefacts are given meaning through crowdsourced nostalgia. The online archive stresses on the idea that the stories and conversations about the artefact by people visiting the archive should be a part of the artefact itself. It is a reflection on traditional methods of preserving and displaying objects through proposing an alternative navigation system by translating physical artefacts into a digital space.", makeSmall: false
}, {
title: "Interacting with 3D objects", img1: require("../assets/wadah/pinStill.jpg"), info: "dummydata", makeSmall: false
}, {
title: "Designing Pins and Signage", img1: require("../assets/wadah/pins.png"), info: "dummydata", makeSmall: true
},{
title: "Home and Index Navigation", img1: require("../assets/wadah/home1.jpg"), img2: require("../assets/wadah/home3.jpg"), img3: require("../assets/wadah/home2.jpg"), img4: require("../assets/wadah/index.jpg"), img5: require("../assets/wadah/index2.jpg"), info: "dummydata", makeSmall: false
},{
title: "User Flow", img1: require("../assets/wadah/wireflow.png"), info: "dummydata", makeSmall: false
},
],
visibleSlide: 0,
counter: 1
}
}
methods: {
storyboard(event) {
if (this.visibleSlide === 3) {
let ele = event.target
this.counter++
ele.src = this.slides[3].img + this.counter
// console.log(this.slides[3].img + 2)
// console.log(ele.src, this.counter)
}
}
}
const obj = {
title: "Home and Index Navigation",
img1: "../assets/wadah/home1.jpg",
img2: "../assets/wadah/home3.jpg",
img3: "../assets/wadah/home2.jpg",
img4: "../assets/wadah/index.jpg",
}
let counter = 2
console.log("Incorrect:", obj.img + counter) // obj.img does not exists = undefined
console.log("Correct:", obj["img"+counter])

How to show icon next to value in cloumn in aurelia slickgrid/slickgrid?

I want to show en edit icon next to value in Amount column. This is because the Amount column is actually editable.But to give that as a hint to user, i want to show some edit icon next to it. How to do that in aurelia slickgrid?
Or maybe there is a way to highlight a field on hover ?
I am using aurelia slickgrid and looking if there is some option in aurelia slickgrid itself.
Go to the aurelia slickgrid example link and click on the link of example's source code
When you open it, there is a method called defineGrids
/* Define grid Options and Columns */
defineGrids() {
this.columnDefinitions1 = [
...,
...,
...,
...,
...,
{ id: 'effort-driven', name: 'Effort Driven', field: 'effortDriven', formatter: myCustomCheckmarkFormatter, type: FieldType.number, sortable: true, minWidth: 100 }
];
... rest of the code
}
The row with id effort-driven is where the icons are placed. On the other words, when you push a data collection(usually array of json object) to the table, values of the data objects with key name effort-driven are given to column with id effort-driven. Furthermore, for each passed value to the column, the method myCustomCheckmarkFormatter reformat it(for example 0 -> false or null -> not filled) and place it to the corresponding table's cell. look at the below method:
// create my custom Formatter with the Formatter type
const myCustomCheckmarkFormatter: Formatter<DataItem> = (_row, _cell, value) => {
// you can return a string of a object (of type FormatterResultObject), the 2 types are shown below
return value ? `<i class="fa fa-fire red" aria-hidden="true"></i>` : { text: '<i class="fa fa-snowflake-o" aria-hidden="true"></i>', addClasses: 'lightblue', toolTip: 'Freezing' };
};
As you can see, when the method is called, it returns an icon such as <i class="fa fa-fire red" aria-hidden="true"></i> which is placed in the table's cell.
I added an edit icon next to Amount,
{
id: "Edit",
field: "edit",
excludeFromColumnPicker: true,
excludeFromExport: true,
excludeFromQuery: true,
excludeFromGridMenu: true,
excludeFromHeaderMenu: true,
minWidth: 30,
maxWidth: 30,
formatter: Formatters.editIcon,
},
and used this custom format from ghiscoding comment:
const customEditableInputFormatter: Formatter = (_row, _cell, value, columnDef, dataContext, grid) => {
const isEditable = !!columnDef.editor;
value = (value === null || value === undefined) ? '' : value;
return isEditable ? `<div style="background-color: aliceblue">${value}</div>` : value;
};
The result is as shown in the picture.

Vue, how to get an empty line if I select an option?

There is a dropdown menu with 3 selections. Whatever you select, it will be shown as text on the right.
How do I manage that the "Choice1" is not shown at all? It should be just an empty line if you click on "Choice1" while "Choice2" and "Choice3" are still shown. Right now all three options are shown.
{ id: 2, value: "Choice1" },
{ id: 3, value: "Choice2" },
{ id: 4, value: "Choice3" },
],
v-model="Example.addressUserModel"
:items="addressitems"
return-object
item-text="value"
item-value="id"
dense
outlined
rounded
v-if="Example.addressUserModel" style="text-align: left; margin-top: 1%">
{{Example.addressUserModel.value}} ```
Replace the interpolation content by
{{Example.addressUserModel.value !== 'Choice1' ? Example.addressUserModel.value : ''}}
Above I have used the ternary operator to check if the selected value is Choice1 . If yes then print '' else print the selected option

Aurelia repeat.for within repeat.for

I will try and keep this as simple as possible.
We have a list of stations, each station has the ability to have up to 4 channels set.
Each station you can change any of the 4 stations.
There is also a summary table below the form that shows what was chosen.
Any change made to the station level updates on the summary table below, but any update to the channel does not. I am wondering if this is something to do with the answer here https://stackoverflow.com/a/42629584/9431766
What I am confused about is if the station display updates, but the channels do not update.
Here is a simplified version of the code
constructor() {
this.stations = [
{
name: 'Station 1',
channels: [null, null, null, null]
},
{
name: 'Station 2',
channels: [null, null, null, null]
},
{
name: 'Station 3',
channels: [null, null, null, null]
}
];
this.channels = [
{ id: 1, name: 'Channel 1' },
{ id: 2, name: 'Channel 2' },
{ id: 3, name: 'Channel 3' },
{ id: 4, name: 'Channel 4' },
];
this.activeStation = {}
}
editStation(station) {
this.activeStation = station;
}
<div class="station">
<input value.bind="activeStation.name"/>
<div repeat.for="select of activeStation.channels">
<select value.bind="activeStation.channel[$index]">
<option model.bind="item" repeat.for="item of channels"></option>
</select>
</div>
</div>
<div class="summary">
<div repeat.form="station of stations">
<h3>${station.name}</h3>
<div repeat.for="channel of station.channels">
${channel ? channel.name : 'N/A'}
</div>
<div class="edit"><a click.delegate="editStation(station)">Edit</a></div>
</div>
</div>
If I reset the channels for each station after they have updated, only then does the summary update.
I do this by using map to re-map the stations, ie;
this.activeStation.channels = this.activeStation.channels.map(station);
I would prefer to not have to reset the channels after each update, this seems like a bit of overkill.
Nice question. The behavior you observed is because the repeat at the <div/> inside div.summary element couldn't see the changes to the array, since the mutation is done via index setter (caused by <select/> binding). So we have 2 choices:
Make the mutation to channels array of each station notify the array observer
Make the repeat aware of changes inside the array.
For (2), we can do it either in your way, or a value converter way to avoid modifying source array on edit. You can see an example here https://codesandbox.io/s/httpsstackoverflowcomquestions59571360aurelia-repeat-for-within-repeat-for-yuwwv
For (1), we need to resolve to manual change handling of the select, via change event
EDIT: in v2, we already fixed this issue so it will properly & naturally work without us having to add these work around.

WebdriverIO: what is the equivalent of elementIdHtml?

How do I get an element's inner HTML from an elementId using browser object?
Is there something like elementIdHtml available in the WebdriverIO API?
The getHTML link for v4 is returning 403 Forbidden.
my goal is that i need to get all text inside all a._3cnp from an elementId
example html
<div class="container">
<a class="_3cnp">first link</a>
<a class="_3cnp">second link</a>
<a class="_3cnp">third link</a>
</div>
need to convert that to ["first link", "second link", ..]
i have the .container elementId already
this is what i did
.then(() => browser.elementIdElements(someElementId, 'a._3cnp'))
.then(buttonElem => {
console.log('->', buttonElem)
console.log('-->', buttonElem.getHTML)
buttonElem.getHTML().then(x => console.log('---->', x))
return buttonElem.value
})
result of elementIdElements is
buttonElem
{ sessionId: '2e2f144c8895a03da1b8df92f4613a33',
status: 0,
value:
[ { ELEMENT: '0.6603119466268468-24',
'element-6066-11e4-a52e-4f735466cecf': '0.6603119466268468-24' } ],
selector: 'a._3cnp' }
but buttonElem.getHTML is undefined
im using webdriverio standalone from botium-webdriverio-connector
LE:
Change your code accordingly to the following:
.then(() => browser.elementIdElements(someElementId, 'a._3cnp'))
.then(buttonElem => {
// buttonElem's 'value' will contain a list of all the matching elements
// thus, you have to call getHTML() on each item from 'value'
// the following will return the HTML of the first matching element
console.log('\nPrint element HTML: ' + buttonElem.value[0].getHTML());
return buttonElem.value[0].getHTML();
})
A better approach would be to loop between them & print the HTML:
.then(() => browser.elementIdElements(someElementId, 'a._3cnp'))
.value.forEach(buttonElem => {
console.log('\nPrint element HTML: ' + buttonElem.getHTML());
return buttonElem.getHTML();
})
The .getHTML() property is scoped to all the ELEMENT objects. For the sake of more didactical approach, I'm going to consider the task to be manipulating the HTML code found in a series of list items (<li>), from am unordered list (<ul>).
So you can do the following:
browser.getHTML('ul.ourList li.ourListItems') (this will return a list of all the <li>'s HTML code)
browser.element('ul.ourList li.ourListItems').getHTML() (this will return the first <li>'s HTML code)
$('ul.ourList li.ourListItems').getHTML() (this is the equivalent of the command above, only a relaxed version)
If you need to iterate through all the <li>s & get the HTML, do this:
let locator = 'ul.ourList li.ourListItems';
browser.elements(locator).value.forEach(elem => {
let elemHTML = elem.getHTML();
console.log( JSON.stringify(elemHTML) );
elemHTML.doSomethingWithIt();
})
where, elem will is an object with the following format:
{ ELEMENT: '0.285350058261731-1',
'element-6066-11e4-a52e-4f735466cecf': '0.285350058261731-1',
selector: 'ul li.fw-item.fz-16.lh-36.pos-r',
value: { ELEMENT: '0.285350058261731-1' },
index: 0
}