I´ve been wondering if is possible to set in an object some items with values being void functions, thus once this object is iterated in HTML, on a click i could trigger those methods functionalities.
Lets say i have two methods
public method1():void{
...do something
},
public method2():void{
...do something
}
then i create an object containing this to methods of type void:
const objArray=[
{click:this.method1()},
{click:this.method2()}
]
then the idea would be to iterate over this array of objects in the HTML and trigger its functionality
HTML
<ul >
<span *ngFor="let item of objArray">
<a
(click)="(item.click)"
>
</a>
</span>
</ul>
on this approach as expected the value of each item is undefined thus I tried to modified the methods array to :
const objArray=[
{click:()=>this.method1()},
{click:()=>this.method2()}
]
Still not triggering anything.
How can i improve this ?
Thanks in advance!
TLDR you forgot brackets in your html
<ul>
<span *ngFor="let item of objArray">
<a (click)="item.click()">Click Me</a>
</span>
</ul>
You can write it this way to assign a reference to the methods:
With this way, any uses of this inside the method will refer to the new object and not your component
const objArray=[
{ click: this.method1 },
{ click: this.method2 }
]
or this way to create a new function that executes the methods:
With this way, this inside the method will refer to your component
const objArray=[
{ click: () => this.method1() },
{ click: () => this.method2() }
]
But in either case you forgot to actually call the function in your html (no brackets)
<ul>
<span *ngFor="let item of objArray">
<a (click)="item.click()">Click Me</a>
</span>
</ul>
Example: https://stackblitz.com/edit/angular-ivy-8awbxg?file=src/app/app.component.ts
Related
I am trying to pass data to a single modal instance and reuse it multiple times inside a loop. It is working but whenever I'm clicking over an image, I'm getting an error - You may have an infinite update loop in a component render function.
This is the html where I'm looping over an array of images and passing it to a modal instance.
<li v-for="(source, i) in sources()" :key="i+'K'">
<span v-b-modal.fancybox #click="fancyBox(source)">
<p>click me</p>
</span>
</li>
This is the html for bootstrap-vue modal -
<b-modal
id="fancybox"
:modal-class="myclass"
hide-footer
centered
>
<img class="fancybox" :src="resource">
</b-modal>
Following is the vue js code -
export default {
data: () => ({
myclass: ['myclass'],
srcItems: [],
resource: ''
}),
methods: {
sources () {
this.srcItems = [
'https://picsum.photos/id/0/5616/3744',
'https://picsum.photos/id/1/5616/3744',
'https://picsum.photos/id/10/2500/1667',
'https://picsum.photos/id/100/2500/1656',
'https://picsum.photos/id/1000/5626/3635'
]
return this.srcItems
},
fancyBox (source) {
this.resource = source
}
}
}
I couldn't able to figure out what is wrong here! Please help me. Thank you for your time.
Hope this will help you to get started
**[LIVE DEMO](https://codepen.io/boussadjra/pen/xxERwZm)**
I have this example html, for which I have the following xpaths defined in a POM:
<button>
Foo
<i class="myClass" label="a label">Something</i>
</button>
<button>
Bar
<i class="myClass" label="another label">Something</i>
</button>
class myPage {
constructor() {
this.fooButton = () => $('//button[text()=\'Foo\']');
this.barButton = () => $('//button[text()=\'Bar\']');
}
}
I want to access the inner text from the myClass iframe, but don't want to define new constructor elements for it - feels like repeating code:
this.insideSomething = () => $('//button[text()=\'Foo\']/i[text()=\'Something\']');
Is there a way to perhaps only define the end of the xpath in its own function? Something like this:
somethingText(parentElement) {
return parentElement + '/i[text()=\'Something\']';
}
... so I can call it like this, for example:
expect(somethingText(MyPage.FooButton).isDisplayed()).to.be.true;
You could try using the "starts with" attribute selector operator ^=:
this.fooButton = () => $('//button[text()^=\'Foo\']');
More info on attribute selectors
I'm writing a function to update a custom checkbox when clicked (and I don't want to use native checkbox for some reasons).
The code for checkbox is
<div class="tick-box" :class="{ tick: isTicked }" #click="() => isTicked = !isTicked"></div>
which works find.
However, there are so many checkboxes, so I use object to keep track for each item. It looks like this
<!-- (inside v-for) -->
<div class="tick-box" :class="{ tick: isTicked['lyr'+layer.lyr_id] }" #click="() => {
isTicked['lyr'+layer.lyr_id] = !isTicked['lyr'+layer.lyr_id]
}"></div>
Now nothing happens, no error at all.
When I want to see isTicked value with {{ isTicked }}, it's just shows {}.
This is what I define in the <script></script> part.
export default {
data() {
return {
isTicked: {},
...
};
},
...
}
Could you help me where I get it wrong?
Thanks!
Edit:
I know that declaring as isTicked: {}, the first few clicks won't do anything because its proerty is undefined. However, it should be defined by the first/second click not something like this.
Objects does not reflect the changes when updated like this.
You should use $set to set object properties in order to make them reactive.
Try as below
<div class="tick-box" :class="{ tick: isTicked['lyr'+layer.lyr_id] }" #click="onChecked"></div>
Add below method:
onChecked() {
this.$set(this.isTicked,'lyr'+this.layer.lyr_id, !this.isTicked['lyr'+this.layer.lyr_id])
}
VueJS watches data by reference so to update object in state you need create new one.
onChecked(lyr_id) {
const key = 'lyr'+lyr_id;
this.isTicked = {...this.isTicked, [key]: !this.isTicked[key]};
}
In my app component below I want to hide a div based on a function I have defined but it brings an error saying
TypeError: Cannot read property 'setState' of undefined
Please what may be wrong
class Apps extends Component {
constructor(props) {
super(props);
// Don't do this!
this.state = { showing: true };
}
render() {
return (
<div>
<div className="container">
<div style={{ display: (this.state.showing ? 'block' : 'none') }}>
A Single Page web application made with react
</div>
</div>
<div className="buttons">
<a href='' onClick={this.onclick} >Login</a>
<br/>
<a href='' >Signup</a>
<br />
<a href='' >Members</a>
</div>
</div>
);
}
onclick(e){
e.preventDefault();
this.setState({showing: false});
}
}
You can use bind or you can just use an arrow ES6 function instead of binding it
onclick = (e) => {
e.preventDefault();
this.setState({ showing: false });
}
You can e.g. bind the function to this in the render method so that this will be what you expect in your onclick method. You can read more about why this is the case in the documentation.
<a href='' onClick={this.onclick.bind(this)}>Login</a>
#Tholle is right. You have to bind your onclick function to current class instance using this. By default this here points to global window obj, which does not have setState function.
Either you bind your function to this, where you are calling it as tholle suggests.
You can also bind it to this in constructor after calling super(props):
this.onclick = this.onclick.bind(this);
this can also be bound implicitly using arrow function like this:
< a href="" onClick={e=>this.onclick(e)} ... ./>
Best practice is to use 2nd option. As using 1st and 3rd options will create new references for the functions each time component renders. However, that's ok to use 1st or 3rd option if you have no problem with memory consumption or creating a small app.
You can use ES6 arrow functions to bind lexical this:
href='' onClick= {(e) => this.onclick(e)}
I got my data from firebase, looped through it and displayed it on the frontend. Now I am trying to get the refs value of the already displayed value when I click on it. For example, when I click on Dino, i should be able to see the value 'Dino' on my console tab of Chrome browser.
Here is a link to the picture of the array list displayed on react frontend
<ul>
<li onClick={this.handleSubmit}>
{
Object.keys(this.props.group).map(function(keyName, keyIndex) {
return(
<div key={keyIndex}>{keyName}</div>
)
})
}
</li>
</ul>
Assuming that those "dino, magic & muu" are the keys in this.props.group you need to add an onClick handler to that div, so:
<div key={keyIndex} onClick={() => console.log(keyName)}>{keyName}</div>
You'll need to bind a click event to each div within the li. I would actually rewrite it like so:
<ul>
{
Object.keys(this.props.group).map( (keyName, keyIndex) => {
return(
<li key={keyIndex} onClick={this.handleSubmit.bind(this, keyName}>
{keyName}
</li>
)
})
}
</ul>
Then your handleSubmit function will get the keyName as a param:
handleSubmit(keyName){
// Do something...
}