javascriptlaraveltwitter-bootstrapvue.jslaravel-spark

Vue ReferenceError: slugify is not defined


So I am trying to make it possible to take the value from one input, and turn it into a slug, to be displayed on another input. I'm using Laravel Spark, Vue, and Bootstrap 4.

So far, I have this as my content in listings.blade.php

<createlisting inline-template>
  <div class="container">
    
  <h1>
    Create a listing
  </h1>
  <form class="form">
      <div class="form-group">
    <label for="name">Name</label>
    <input type="text" class="form-control" v-on:keyup="listingslug" id="name" name="name" placeholder="Example input placeholder">
  </div>
      <label for="slug">Your vanity URL</label>
<div class="input-group mb-3">
  <div class="input-group-prepend">
    <span class="input-group-text" id="basic-addon3">{{ env('APP_URL') }}/listing/</span>
  </div>
  <input type="text" class="form-control" id="slug" name="slug" aria-describedby="basic-addon3">
</div>
  </form>
</div>
</createlisting>

I have this in a createlisting.js file

Vue.component('createlisting', {
    data() {
        return {
            form: new SparkForm({
                name: '',
                description: ''
            })
        };
    },
    methods: {
      slugify: function(text) {
        return text
          .toString()                     // Cast to string
          .toLowerCase()                  // Convert the string to lowercase letters
          .normalize('NFD')       // The normalize() method returns the Unicode Normalization Form of a given string.
          .trim()                         // Remove whitespace from both sides of a string
          .replace(/\s+/g, '-')           // Replace spaces with -
         .replace(/[^\w\-]+/g, '')       // Remove all non-word chars
          .replace(/\-\-+/g, '-');        // Replace multiple - with single -
      },
      listingslug: function(text) {
        document.getElementById("slug").value = this.slugify(text); 
      }
    }
});

I added the slugify function from my custom.js file, which the function is showed below, to my Vue componenet, to see if that helps.

/**
*   This is the slugify function, to allow us to slugify text
*/
function slugify(text) {
  return text
    .toString()                     // Cast to string
    .toLowerCase()                  // Convert the string to lowercase letters
    .normalize('NFD')       // The normalize() method returns the Unicode Normalization Form of a given string.
    .trim()                         // Remove whitespace from both sides of a string
    .replace(/\s+/g, '-')           // Replace spaces with -
    .replace(/[^\w\-]+/g, '')       // Remove all non-word chars
    .replace(/\-\-+/g, '-');        // Replace multiple - with single -
}

I'm very new when it comes to Vue, and still pretty beginner in terms of Javascript. What am I doing wrong?

Another part, was once changing my slugify(text) in the vue template to this.slugify(text), it was outputted as "object-keyboardevent".


Solution

  • I think that part of the problem here is that for your input that you are entering text you are wanting to be 'slugified', the data being entered is not bound to the 'name' value properly (at least not in a 'Vuey' way).

    You can do so by binding it using v-model like so:

    //note that I removed your v-on:keyup, and placeholder="Example input placeholder" for simplicity/demo purposes
    
    <input type="text" class="form-control" id="name" name="name" v-model="name">
    

    See the Vue docs on v-model/Form input bindings: https://v2.vuejs.org/v2/guide/forms.html

    Instead of using a keyup, you might consider using a button that listens for a click using @click. Then you could call your method 'listingslug' with a click instead.

    So that would look kind of like this:

    <button @click="listingslug">Slugify</button>
    

    For more detail about events see the official Vue documentation on the subject: https://v2.vuejs.org/v2/guide/events.html

    Then you might have the 'slugified' output input value set to a data value like this:

    <input type="text" class="form-control" id="slug" name="slug" value="{{slugified}}" aria-describedby="basic-addon3">
    

    But for this to work, you would also need to add 'slugified' to your data attributes, and declare it as an empty string or NULL value (as you have already done with the name data attribute).

    That would change your listingslug method to look something like this:

    
    listingslug: function() {
            this.slugified = this.slugify(this.name); 
          }