简体   繁体   中英

Setting value for specific ember component

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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM