symfony 从rest API刺激构建html元素

rn0zuynd  于 2022-11-16  发布在  其他
关注(0)|答案(2)|浏览(159)

你好,我在我的symfony项目中有一个刺激代码。这个代码调用了一个rest API,它需要大约3秒的时间来提供响应。这个rest API返回JSON。
这是我的代码:

import {Controller} from "@hotwired/stimulus";
import axios from "axios";

export default class extends Controller {
    static values = {
        url: String
    }

    connect() {
        axios.get(this.urlValue)
            .then((r) => {
                if (r.data !== null) {
                    let html
                    const tmp = JSON.parse(r.data)
                    if (tmp === null) {
                        html = document.createElement("div")
                        html.classList.add("alert", "alert-danger", "alert-dismissible", "fade", "show")
                        html.innerHTML += "Asset Number Not Valid";
                        html.innerHTML += "<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>"
                    } else {
                        html = document.createElement("ul")
                        html.classList.add("list-group")
                        for(let key in tmp) {
                            html.innerHTML += "<li class=\"list-group-item\">" + key + " : " + tmp[key] + "</li>";
                        }
                        html.innerHTML += "</ul>";
                    }
                    this.element.replaceWith(html);
                }
            })
    }
}

正如你所看到的,它正在构建一个列表或者显示一个错误。这段代码真的很简单,而且运行得很好。我只是不喜欢html的构建方式。
你有其他更干净的方法吗?

nue99wik

nue99wik1#

下面是一种不同的方法,基本上是利用HTML Template元素将所有HTML移回到HTML文件中。
当您在Stimulus控制器中构建太多HTML时,它可能会变得很混乱,而不是考虑目标的力量,因为它能够针对任何元素,包括模板,甚至是您动态添加的东西。

控制器

  • 我们为HTML创建了一些template目标,在注入时将其用作复制基础。
  • 我们还有一个error和item '目标名称,以便能够轻松删除任何错误或添加的项。
  • results目标将包含注入的结果(项目模板)。
  • 此外,为了安全起见,我们将使用innerText而不是innerHtml
import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
  static targets = [
    'error',
    'errorTemplate',
    'item',
    'itemTemplate',
    'results',
  ];

  static values = {
    url: String,
  };

  connect() {
    this.clearError();
    this.clearResults();

    fetch(/* or axios */)
      .then(/* json parsing etc */)
      .then((items) => {
        items.forEach((value) => {
          this.addResultItem(value);
        });
      })
      .catch((error) => {
        // be sure to handle errors using nice promise like thing
        this.showError(error);
      });
  }

  clearError() {
    this.errorTarget && this.errorTarget.remove();
  }

  clearResults() {
    this.resultItemTargets.forEach((itemElement) => {
      itemElement.remove();
    });
  }

  showError() {
    const alert =
      this.errorTemplateTarget.content.firstElementChild.cloneNode(true);
    this.prepend(alert);
  }

  addResultItem(value) {
    const item =
      this.itemTemplateTarget.content.firstElementChild.cloneNode(true);
    item.innerText = value;
    this.resultsTarget.append(item);
  }
}

HTML格式

  • 这里我们有基本的template元素,可以为erroritem部分设置任何想要的HTML。
  • template元素的目标名称以template结尾
  • 请注意,ul始终位于DOM中,但如果其中没有项,则可以使用css :empty默认隐藏它。
<section class="container" data-controller="results"
  data-results-url-value="https://myapi">
  <template data-results-target="itemTemplate">
    <li class="list-group-item" data-results-target="item">__VALUE__</li>
  </template>
  <template data-results-target="errorTemplate">
    <div data-results-target="error" class="alert alert-danger
      alert-dismissible fade show" role="alert">
      <!-- remember accessibility - use proper titles & role=alert when putting things in DOM -->
      <button type="button" class="btn-close" data-bs-dismiss="alert"
        aria-label="Close"></button>
      <h3>Asset Number Not Valid</h3>
      <p>Details about the thing</p>
    </div>
  </template>
  <!-- use css to hide if :empty -->
  <ul class="list-group" data-results-target="results">
  </ul>
</section>

有用链接

7rtdyuoh

7rtdyuoh2#

您可以在connect方法下面的分隔函数中创建HTML,例如:

errorMessage() {
  const div = document.createElement("div");
  div.innerHTML = `
    <p>Some HTML here</p>
    ... More html

  `

  return div;
}

然后作为回应,您只需呼叫:

this.errorMessage();

成功的响应也是一样的,所以在最后的响应中,你可以用this.errorMessage()或者this.appendList(),或者你想用什么来调用你的函数。

相关问题