Y
Y
yura_born2021-06-20 16:52:58
typescript
yura_born, 2021-06-20 16:52:58

How to create a generic class for creating a form in JS?

Hello!
Help me figure it out, I need to display almost the same 2 forms on the page with different inputs: I
wrote a class for the form:

import Button from '../button/button';
import InputField from './inputField';

export default class Form {
  id = '';
  classes: string[] = [];

  constructor(id: string, ...classes:string[]) {
    this.id = id;
    this.classes = classes;
  }

  render():HTMLElement {
    const element = document.createElement('form');
    this.classes.forEach(className => element.classList.add(className));
    element.setAttribute('id', this.id);
    element.innerHTML = `
        ${new InputField('text', 'carName', 'create-name', '', 'create-name').render().outerHTML}
        ${new InputField('color', 'create-color', 'create-color', '#FFFFFF', 'create-color').render().outerHTML}
        ${new Button('submit', 'create-car-submit', 'Create', 'btn', 'blue') .render().outerHTML}
`;
    return element;
  }
}


And also a class for inputs:
export default class InputField {
  classes: string[] = [];

  constructor(
    readonly typeInput: string,
    readonly nameInput: string,
    readonly id: string,
    readonly value: string,
    ...classes:string[]
  ) {

    this.typeInput = typeInput;
    this.nameInput = nameInput;
    this.id = id;
    this.value = value;
    this.classes = classes;
  }

  render(): HTMLElement{
    const element: HTMLElement = document.createElement('input');
    this.classes.forEach(className => element.classList.add(className));
    element.setAttribute('type', this.typeInput);
    element.setAttribute('id', this.id);
    element.setAttribute('name', this.nameInput);
    element.setAttribute('value', this.value);
    return element;
  }
}


I put an instance of the form class on the page:

const html = `
    <div class="main-container">    
    <div class="top-menu">
      ${new Button('', 'menu-garage-btn', 'To garage', 'btn', 'green') .render().outerHTML}
      ${new Button('', 'menu-winners-btn', 'To winners', 'btn', 'green') .render().outerHTML}
    </div>
    <div class="settings-wrp" id="settings">
      ${new Form('form-create-car', 'settings', 'settings-form').render().outerHTML}


      <form action="" class="settings-form" id="form-update-car">
        <input type="text" class="update-name" id="update-name" disabled>
        <input type="color" class="update-color" id="update-color" value="#FFFFFF" disabled>
        <button class="btn blue disabled" data-id="-1" id="update-car-submit" type="submit">Update</button>
      </form>
    </div>
    <div class="control-race-btn-wrp">
      <button class="btn green" id="btn-start-race">Race</button>
      <button class="btn green" id="btn-reset-race">Reset</button>
      <button class="btn blue" id="btn-generate-cars">Generate cars</button>
    </div>
  
    <div class="garage-wrp" id="garage-wrp">
    <h2>Garage (${store.garage.carsCount})</h2>
    <h3>Page # ${store.garage.carsPage}</h3>
    <div>
      ${store.garage.showGarage().join('')}
    </div>
    <div class="pagination-wrp" id="pagination-wrp">
      <button class="btn blue ${btnPrevGarageState}" id="btn-garage-prev">Prev</button>
      <button class="btn blue ${btnNextGarageState}" id="btn-garage-next">Next</button>
    </div>
    </div>
  
    <p class="winner-text invisible" id="winner-text"></p>
  
    <div class="winners-view hidden" id="winners-view">
   
    </div>  
  </div>
    `;
    const root = document.createElement('div');
    root.setAttribute('id', 'app');
    root.innerHTML = html;
    document.body.appendChild(root);
  };


Everything works well, but I need another one of the same form, only it will have different inputs (other classes and id). Suggest an idea how to make the form class more generic? Why not write your own render method under another form? Can someone thread faced?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sergey Kotov, 2021-06-20
@yura_born

fields: {type: TypeEnum; classNames: string[]; id: string}[];

render() {
  const mappedFields: HTMLElement[] = this.fields.map(field => new InputField(field.type, ...field.classNames).render());
  this.element.append(...mappedFields);
  this.element.append(new Button('submit', 'create-car-submit', 'Create', 'btn', 'blue') .render());
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question