4
\$\begingroup\$

I'm trying to create a complex application—Table generator. And the first part if it is form that lets user input data source. As I figure source should be an absolute http url, so I have to give user <input> with validation, and <button> which will reflect validation state.

Eventually I came up with this:

class Form {
  constructor () {
    this.button            = document.createElement('button')
    this.button.innerHTML  = 'Upload'
    // Initially it's empty so it's invalid
    this.button.disabled   = true

    this.input             = document.createElement('input')
    this.input.placeholder = 'Path to data'
    // Let's assign our custom validator
    // since validation props are read only
    this.input.oninput     = () => this.validate()
  }
  validate () {
    // Tribute @LukeP
    // https://stackoverflow.com/a/34695026/2626747
    // Let's use anchor superpowers
    // rather then google `url regex`
    const a = document.createElement('a')
    a.href  = this.input.value
    // If typed value couldn't be parsed as an absolute url,
    // it'd be considerd as a path on current host
    this.button.disabled = !(a.host && a.host != window.location.host)
  }
  render () {
    const form = document.createElement('form')
    form.appendChild(this.input)
    form.appendChild(this.button)
    return form
  }
}

const form = new Form()
document.getElementById('app').appendChild(form.render())

I'm not satisfied with this code, and I can not explain why. I don't have somewhat strong experience in JS, so I'm relying on your peer review.

Help me make Web better, starting with my app.

\$\endgroup\$
0

1 Answer 1

2
\$\begingroup\$

I'd just move the render part to the constructor and provide it with the id of the parent element.

class Form {

   constructor( id ) {

      const button = document.createElement('button');
      button.value = "Upload";
      button.disabled = true;

      const input = document.createElement('input');
      input.placeholder = 'Path to data';
      input.oninput = () => this.validate();

      this.input = input;
      this.button = button;

      const form = document.createElement('form');
      form.appendChild(input);
      form.appendChild(button);
      document.getElementById(id).appendChild(form);

   }

   validate () {

      const a = document.createElement('a');
      a.href = this.input.value;
      this.button.disabled = !(a.host && a.host != window.location.host);

   }

}

const form = new Form("app");

It depends what you want to do with the form afterwards.

\$\endgroup\$
1

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.