mercredi 4 août 2021

TypeScript Decorator and Private class method was not called

I just get started learning TypeScript and I am making a simple "add project" app which I follow a tutorial

This is the index.html file, not much to talk about this file because it is just where to manipulate DOM by the id of HMTL element

here is app.css file:

* {
  box-sizing: border-box;
}

html {
  font-family: sans-serif;
}

body {
  margin: 0;
}

label,
input,
textarea {
  display: block;
  margin: 0.5rem 0;
}

label {
  font-weight: bold;
}

input,
textarea {
  font: inherit;
  padding: 0.2rem 0.4rem;
  width: 100%;
  max-width: 30rem;
  border: 1px solid #ccc;
}

input:focus,
textarea:focus {
  outline: none;
  background: #fff5f9;
}

button {
  font: inherit;
  background: #ff0062;
  border: 1px solid #ff0062;
  cursor: pointer;
  color: white;
  padding: 0.75rem 1rem;
}

button:focus {
  outline: none;
}

button:hover,
button:active {
  background: #a80041;
  border-color: #a80041;
}

.projects {
  margin: 1rem;
  border: 1px solid #ff0062;
}

.projects header {
  background: #ff0062;
  height: 3.5rem;
  display: flex;
  justify-content: center;
  align-items: center;
}

#finished-projects {
  border-color: #0044ff;
}

#finished-projects header {
  background: #0044ff;
}

.projects h2 {
  margin: 0;
  color: white;
}

.projects ul {
  list-style: none;
  margin: 0;
  padding: 1rem;
}

.projects li {
  box-shadow: 1px 1px 8px rgba(0, 0, 0, 0.26);
  padding: 1rem;
  margin: 1rem;
}

.projects li h2 {
  color: #ff0062;
  margin: 0.5rem 0;
}

#finished-projects li h2 {
  color: #0044ff;
}

.projects li h3 {
  color: #575757;
  font-size: 1rem;
}

.project li p {
  margin: 0;
}

.droppable {
  background: #ffe3ee;
}

#finished-projects .droppable {
  background: #d6e1ff;
}

#user-input {
  margin: 1rem;
  padding: 1rem;
  border: 1px solid #ff0062;
  background: #f7f7f7;
}



<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>ProjectManager</title>
    <link rel="stylesheet" href="app.css" />
    <script src="dist/app.js" defer></script>
  </head>
  <body>
    <template id="project-input">
      <form>
        <div class="form-control">
          <label for="title">Title</label>
          <input type="text" id="title" />
        </div>
        <div class="form-control">
          <label for="description">Description</label>
          <textarea id="description" rows="3"></textarea>
        </div>
        <div class="form-control">
          <label for="people">People</label>
          <input type="number" id="people" step="1" min="0" max="10" />
        </div>
        <button type="submit">ADD PROJECT</button>
      </form>
    </template>
    <template id="single-project">
      <li></li>
    </template>
    <template id="project-list">
      <section class="projects">
        <header>
          <h2></h2>
        </header>
        <ul></ul>
      </section>
    </template>
    <div id="app"></div>
  </body>
</html>

the index.html file has a script from dist/app.js which is generated from app.ts. This is the app.ts file:

// autobind decorator
function autobind (_: any, _2: string, descriptor: PropertyDecorator) {
  console.log('start autobind')
  console.log(_, _2, descriptor)
  const originalMethod = descriptor.value
  const adjDescriptor: PropertyDecorator = {
    configurable: true,
    get () {
      const boundFn = originalMethod.bind(this)
      return boundFn
    }
  }
  return adjDescriptor
}

// projectInput Class
class ProjectInput {
  templateElement: HTMLTemplateElement
  hostElement: HTMLDivElement
  element: HTMLElement
  titleInputElement: HTMLInputElement
  descriptionInputElement: HTMLInputElement
  peopleInputElement: HTMLInputElement

  constructor () {
    this.templateElement = document.getElementById(
      'project-input'
    )! as HTMLTemplateElement

    this.hostElement = document.getElementById('app')! as HTMLDivElement

    const importedNode = document.importNode(this.templateElement.content, true)
    this.element = importedNode.firstElementChild as HTMLFormElement
    this.element.id = 'user-input'

    this.titleInputElement = this.element.querySelector(
      '#title'
    ) as HTMLInputElement
    this.descriptionInputElement = this.element.querySelector(
      '#description'
    ) as HTMLInputElement
    this.peopleInputElement = this.element.querySelector(
      '#peole'
    ) as HTMLInputElement

    this.configure()
    this.attach()
  }

  private gatherUserInput (): [string, string, number] | void {
    console.log('start gatherUserInput')

    const enteredTitle = this.titleInputElement.value
    const enteredDescription = this.descriptionInputElement.value
    const enteredPeople = this.peopleInputElement.value

    if (
      enteredTitle.trim().length === 0 ||
      enteredDescription.trim().length === 0 ||
      enteredPeople.trim().length === 0
    ) {
      alert('Invalid input, please try again')
      return
    } else {
      return [enteredTitle, enteredDescription, +enteredPeople]
    }
  }

  @autobind
  private submitHandler (event: Event) {
    event.preventDefault()
    const userInput = this.gatherUserInput()
    if (Array.isArray(userInput)) {
      const [title, desc, people] = userInput
      console.log(title, desc, people)
    }
  }

  private configure () {
    this.element.addEventListener('submit', this.submitHandler.bind(this))
  }

  private attach () {
    this.hostElement.insertAdjacentElement('afterbegin', this.element)
  }
}

const prjInput = new ProjectInput()

here is what I gotenter image description here

but it can not access function gatherUserInput and decorator autobind because I tried to console.log but nothing printed out.

This is what terminal logged:

[12:06:19 PM] Starting compilation in watch mode...

src/app.ts:3:37 - error TS2339: Property 'value' does not exist on type 'PropertyDecorator'.

3   const originalMethod = descriptor.value
                                      ~~~~~

src/app.ts:5:5 - error TS2322: Type '{ configurable: boolean; get(): any; }' is not assignable to type 'PropertyDecorator'.
  Object literal may only specify known properties, and 'configurable' does not exist in type 'PropertyDecorator'.

5     configurable: true,
      ~~~~~~~~~~~~~~~~~~

src/app.ts:67:3 - error TS1241: Unable to resolve signature of method decorator when called as an expression.
  Type 'PropertyDecorator' has no properties in common with type 'TypedPropertyDescriptor<(event: Event) => void>'.

67   @autobind
     ~~~~~~~~~

src/app.ts:67:4 - error TS2345: Argument of type 'TypedPropertyDescriptor<(event: Event) => void>' is not assignable to parameter of type 'PropertyDecorator'.
  Type 'TypedPropertyDescriptor<(event: Event) => void>' provides no match for the signature '(target: Object, propertyKey: string | symbol): void'.

67   @autobind
      ~~~~~~~~

[12:06:24 PM] Found 4 errors. Watching for file changes.

Please help me to tackle with it, thank you so much and have a good day




Aucun commentaire:

Enregistrer un commentaire