AppML 案例模板

自定义列表与表单的 HTML 结构,用占位符绑定数据。

Intermediate
Key Points模板就是带 {{字段名}} 占位符的 HTML 片段,AppML 按数据逐条替换后插入页面。

默认渲染 vs 模板

Template
Markup框架生成的表格你写的 HTML
Styling受限于默认类名完全自由
Fields按 items 全列想显示哪些就写哪些
Cost零成本要维护模板

卡片式列表

HTML
<appml-app src="models/customers.xml">
  <appml-template view="list">
    <div class="card">
      <h3>{{company}}</h3>
      <p class="contact">{{contact}} · {{city}}</p>
      <p class="credit">额度:{{credit}}</p>
    </div>
  </appml-template>
</appml-app>
CSS
.card {
  border: 1px solid #e5e7eb;
  border-radius: .5rem;
  padding: 1rem 1.2rem;
  margin-bottom: .8rem;
  background: #fff;
  box-shadow: 0 1px 2px rgba(0,0,0,.04);
}
.card h3 { margin: 0 0 .3rem; font-size: 1.05rem; }
.card .contact { color: #6b7280; margin: 0 0 .4rem; font-size: .9rem; }
.card .credit { margin: 0; font-weight: 600; color: #047857; }
Output
北京云图科技
张伟 · 北京
额度:50000

上海海联贸易
李娜 · 上海
额度:80000

占位符规则

  • **{{字段名}}** —— 替换成该字段的值
  • 不存在的字段 —— 替换成空串,不报错
  • 原样插入 HTML —— 值不会被转义,注意 XSS
Placeholder substitution usually does not escape HTML. A <script> in user data becomes a live tag. Sanitise before display, or escape server-side before storing.

表单模板

HTML
<appml-app src="models/customers.xml">
  <appml-template view="form">
    <div class="field">
      <label>公司名称</label>
      <input name="company" value="{{company}}" required>
    </div>
    <div class="field">
      <label>联系人</label>
      <input name="contact" value="{{contact}}">
    </div>
    <div class="field">
      <label>城市</label>
      <input name="city" value="{{city}}">
    </div>
    <div class="field">
      <label>额度</label>
      <input name="credit" type="number" value="{{credit}}">
    </div>
  </appml-template>
</appml-app>

In a form template the name attribute must match item name; that is how the framework maps values back. name="companyName" silently fails to save.

条件与格式化

HTML
<div class="card">
  <h3>{{name}}</h3>
  <p>库存:{{stock}}</p>
  <p class="tag">{{category}}</p>
</div>

Templates support neither conditionals nor loops. For "red when stock is 0" or thousands separators, pre-process in the controller or post-process the DOM with JS.

JavaScript
function productsController(appml) {
  appml.onload = function () {
    document.querySelectorAll('.card').forEach((card) => {
      const stock = card.querySelector('p:nth-of-type(1)');
      if (stock && stock.textContent.trim() === '库存:0') {
        card.style.borderColor = '#dc2626';
      }
    });
  };
}

Post-processing in onload works but is fragile because it depends on template structure. With many fields, rendering yourself from appml.data is more robust.

什么时候值得写模板

  • 卡片列表 —— 表格放不下的多行信息
  • 品牌化界面 —— 要贴合现有设计系统
  • 不写 —— 内部工具、字段少、只要能用

Friends & Partners