0

I'm using Vue for a small application that copies a piece of dynamic HTML to the user's clipboard after they filled in a form. All works well but I can't seem to reflect changes in the HTML after I have executed the copy method once. I feel like there is something about the virtual DOM that I haven't quite understood and it hinders me finding a solution to the problem.

This is the Vue js:

var app = new Vue({
  delimiters: ['${', '}'], // Alternative delimiters for Twig+Vue
  el: '#app',
  data: {
    lastname: null,
    firstname: null,
    mailto: null,
    occupation: 'Consultant',
    absoluteurl: absBaseUrl,
    companyId: 9, // Default company ID
    companies: []
  },
  computed: {
    logo() {
      return this.absoluteurl + companies[this.companyId].logo;
    },
    setMailto() {
      return 'mailto:' + this.mailto;
    },
    input() {
      return this.$refs.signaturepreview.innerHTML;
    }
    // signatureBanner() {
    //   if (companies[this.companyId].)
    //   return companies[this.companyId].logo;
    // }
  },
  methods: {
    changeComp: function() {
      console.log('company select input changed');
    },
    copyToClipboardFF: function(text) {
      window.prompt ("Copy to clipboard: Ctrl C, Enter", text);
    },
    copySignature: function() {
      // console.log(this.input);
      var success   = true,
          range     = document.createRange(),
          selection;
      // For IE.
      if (window.clipboardData) {
        window.clipboardData.setData("Text", this.input);
      } else {
        // Create a temporary element off screen.
        var tmpElem = $('<div>');
        tmpElem.css({
          position: "absolute",
          left:     "-1000px",
          top:      "-1000px",
        });
        // Add the input value to the temp element.
        tmpElem.text(this.input);
        $("body").append(tmpElem);
        // Select temp element.
        range.selectNodeContents(tmpElem.get(0));
        selection = window.getSelection ();
        selection.removeAllRanges ();
        selection.addRange (range);
        // Lets copy.
        try {
          success = document.execCommand ("copy", false, null);
        }
        catch (e) {
          this.copyToClipboardFF(this.input.val());
        }
        if (success) {
          alert ("Signature is copied to the clipboard!");
          // remove temp element.
          tmpElem.remove();
        }
      }
    }
  },
  mounted() {
  this.companies = companies; // Get json data in the Vue instance
}
})

The relevant part is the computed data input(), and the method copySignature.

And the HTML looks something like this:

<div ref="signaturepreview" id="signature-preview" class="preview-wrapper signature-preview">

  <table class="signature" style="
    All sorts of info fetched from a form with jQuery
  </table>
</div>


<button id="validate-signature" class="button button--green" @click="copySignature">Je valide ma signature</button>

When the button is clicked the input data should be refreshed every time, but it only works once. After that the content on the clipboard just stays the same whatever I do.

1 Answer 1

1

You have defined input as a computed, but it does not reference anything reactive, so its value never gets updated. If you use a method instead, it will be evaluated every time it is called, and you will get the current value.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for those pointers! I had the assumption that a computed value was reassigned every time it is called, for example by a method like copySignature in my code. It seems counter-intuitive that it isn't... I am now looking into directives and will post back when I have found the solution.
A method would be evaluated every time it is called. Now that I think about it, you could probably just use a method instead of a computed.
That seems to work @Roy J! If you add the suggestion to your answer I can go ahead and accept it. Thanks man!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.