Reputation: 4123
I've made a component that copies some code from a code box. The component javascript looks like:
import Ember from 'ember';
export default Ember.Component.extend({
tagName: 'code',
classNames: ['lm-code-box'],
dataTarget: null,
dataTrigger: Ember.computed('dataTarget',
function() {
return `.${this.get('dataTarget')}`;
}
),
copyAction: null,
icon: 'ion-code',
copyStatus: null,
buttonText: 'Copy',
didInsertElement() {
this.clipboard = new Clipboard('.lm-button--copy');
this.clipboard.on('success',(e) => {
this.set('icon','ion-checkmark');
this.set('copyStatus','success');
this.set('buttonText','Copied');
e.clearSelection();
});
this.clipboard.on('error',(e) => {
this.set('icon','ion-android-warning');
this.set('copyStatus','error');
this.set('buttonText','Error');
});
},
willDestroyElement() {
this.clipboard.destroy();
}
});
Component code looks like:
<a class="lm-button--copy {{buttonClass}}" data-clipboard-target={{dataTrigger}} data-clipboard-action={{copyAction}}>
{{buttonText}}
<i class="icon {{icon}}"></i>
</a>
<pre class="{{dataTarget}}">
{{yield}}
</pre>
Then in my template the code looks like:
{{#lm-code-copy dataTarget="testOne"
copyAction="copy"}}
test one
{{/lm-code-copy}}
{{#lm-code-copy dataTarget="testTwo"
copyAction="copy"}}
test two
{{/lm-code-copy}}
Everything copies fine, but in the block:
this.set('icon','ion-checkmark');
this.set('copyStatus','success');
this.set('buttonText','Copied');
changes those key values on both components that are rendered. How can I tell ember to only change the value for the current component? I assumed this
would set that context but it doesn't seem to do the trick.
Upvotes: 0
Views: 154
Reputation: 1444
I'll take a chance here, since you didn't supply your component template. I think you're problem might be with your CSS selector
this.clipboard = new Clipboard('.lm-button--copy');
You're always targeting all .lm-button--copy
elements in the page with that selector. Meaning that each component instance will have a separate this.clipboard
reference but all pointing to the same dom element.
Also the this
you refer to is not the component:
this.clipboard.on('success',(e) => { <--- This `this` is your component
this.set('icon','ion-checkmark');
this.set('copyStatus','success'); <---- These `this` are the context of the invoking success handler (you can set a break point here to see its not the ember component)
this.set('buttonText','Copied');
e.clearSelection();
});
You might want something like this (assuming this Clipboard
thing can also receive a dom element):
this.clipboard = new Clipboard(this.$('.lm-button--copy'));
In an Ember component this.$
refers to the outer div that wraps the component. As such you will only select elements that are within the component. Which I think what you might need.
Upvotes: 1
Reputation: 4123
@Pedro Rio was close. Using clipboard.js you have to pass in a DOM element similar to jquery using syntanx like clipboard = new Clipboard('.class-name')
or clipboard = new Clipboard('#id-name')
. Somehow, in Ember world the scope of this
was bound to the scope of Clipboard.js's query. So the fix was to use Ember's jQuery syntax to scope clipboard to each button item.
this.clipboard = new Clipboard(this.$(`.lm-button--copy`).get(0));
Please note that there is no .
after this.$
as there is in the other answer.
Upvotes: 0