【问题标题】:"attached" or DOM-render equivalent for nested view-model.ref嵌套 view-model.ref 的“附加”或 DOM 渲染等效项
【发布时间】:2016-05-24 21:13:05
【问题描述】:

我们有一个页面,“parent”,它通过在 parent.html 中称为“child”的 view-model.ref 引用一个模板。我们通过单击父页面上的项目来更改此子模板的数据,该父页面使用OpenDetailsDiv 调用子函数。假设我为此事件使用了一个按钮,如下所示:

parent.html

<child view-model.ref="clientusertasks"></child>
<input type="button" value="Click Me" click.trigger="OpenDetailsDiv" />

通过这种方式,我们可以从父视图模型中调用“子”视图模型上的函数,如下所示:

parent.js

import { inject } from 'aurelia-framework';
import { HttpClient } from 'aurelia-fetch-client';
import 'fetch';
import AuthService from 'AuthService';
import { BpoClientUserTasks } from './bpo-client-user-tasks';

@inject(HttpClient, AuthService, BpoClientUserTasks)
export class Parent {
  smallDivObj = {};
  freq = '';
  period = '';
  filterVal = '';
  client = '';

  constructor(http, AuthService, BpoClientUserTasks) {

    http.configure(config => {
      config
        .withBaseUrl("WebServices.asmx/")
        .withDefaults({
          headers: {
            'Accept': 'application/json'
          }
        });
    });

    this.http = http;
    this.auth = AuthService;
    this.clientusertasks = BpoClientUserTasks;
  }


  OpenDetailsDiv(myObject) {
    this.clientusertasks.CallBPOClientUserService(this.freq, this.period, this.filterVal, myObject.TrueClient, myObject.Client);
  }
}

到目前为止一切顺利。 “子”视图模型具有此功能 CallBPOClientUserService,如下所示:

child.js

import { inject } from 'aurelia-framework';
import { HttpClient } from 'aurelia-fetch-client';
import 'fetch';
import AuthService from 'AuthService';

@inject(HttpClient, AuthService)
export class Child {
  smallDivObj = {};

  constructor(http, AuthService) {

    http.configure(config => {
      config
        .withBaseUrl("WebServices.asmx/")
        .withDefaults({
          headers: {
            'Accept': 'application/json'
          }
        });
    });

    this.http = http;
    this.auth = AuthService;
  }

  attached() {

  }

  CallBPOClientUserService(freq, period, filterVal, client, displayClient) {
    $('#TasksByClientByUserDiv').addClass("fade");

    this.freq = freq;
    this.period = period;
    this.filterVal = filterVal;
    this.client = client;

    var mymethod = {
      method: 'post',
      body: JSON.stringify({
        "session": this.auth.session,
        "Client": client,
        "FreqFilter": freq,
        "FilterVal": filterVal
      }),
      headers: {
        'content-type': 'application/json'
      }
    };
    //alert(JSON.stringify(mymethod));
    this.http.fetch('GetBPOTasksByClientByUserDiv', mymethod)
      .then(response => response.json())
      .then(info => {
        this.tasksByClientByUser = JSON.parse(info.d);

        //setTimeout("$('#TasksByClientByUserTable').tablesorter();", 100);  
      });
  }
}

请注意,在函数CallBPOClientUserService 中,我们希望在渲染DOM 之后调用tablesorter 排序函数来对视图中的表进行排序。

通常我会在视图模型的“附加”组件生命周期中调用此函数。但是您可以看到,我们填充此视图的方式来自“父”页面的 view-model.ref,它使“子”的“附加”组件在这种情况下无用(毕竟它只被调用一次加载父级时)。

所以我的问题:

我是否可以利用类似attached 的组件来调用此tablesorter 函数?

我有一个廉价的解决方法,我可以使用我在函数中注释的setTimeout,但我宁愿在 Aurelia 事件中正确执行此操作并保证 DOM 已完成。

【问题讨论】:

  • 您可以尝试将您的函数推送到 microTaskQueue,如本答案stackoverflow.com/questions/35587033/…中所述
  • 是的,我喜欢这样。在调用 jquery 函数之前,我们还考虑使用可绑定事件来结束 table 上的 repeat.for。
  • 试图用bind()代替attached()

标签: aurelia


【解决方案1】:

我相信我对这个问题有 2 个我很满意的解决方案,并将在此处发布它们。

首先是Fabio上面推荐的使用microTaskQueue

另一种解决方案是使用自定义的可绑定事件在此处的 table 上的 repeat.for 完成时调用函数...

<template>
<require from='../tablesorter-bind'></require>

<section id="TasksByClientDiv" class="SmallDivPanel ui-draggable BIBulletinSection100 SmallDivSection hellfire">
    <small-div-header smalldivinfo.bind="smallDivObj"></small-div-header>

    <div id="TasksByClientBox">
        <div style="margin-top: 10px;font-size: 20px;">Frequency: ${freq} / Period: ${filterVal}</div>

        <div id="TasksByClientTableDiv" class="SmallDivMainPanel">
            <table id="TasksByClientTable" >
                <thead class="tablesorter">
                    <tr>
                        <th>Client</th>
                        <th>Received</th>
                        <th>Prepped</th>
                        <th>Loaded</th>
                        <th>Doc Loaded</th>
                    </tr>
                </thead>

                <tbody>
                    <tr click.trigger="OpenDetailsDiv(x)" repeat.for="x of tasksByClient" table-id.bind="tableId">
                        <td>${x.Client}</td>
                        <td>${x.totLoaded}</td>
                        <td>${x.totLoaded}</td>
                        <td>${x.totPrepped}</td>
                        <td>${x.numDocLoaded}</td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
</section>
</template>

其中 tableId 在 View-Model 中定义为我的 tableID

然后我像这样设置自定义元素:

tablesorter-bind.js

import {inject, customAttribute, TaskQueue} from 'aurelia-framework';

@customAttribute('table-id')
@inject(Element, TaskQueue)
export class TablesorterBind {
constructor(element, taskQueue) {
    // "element" will be the DOM element rendered from the template     
    this.element = element;
    this.taskQueue = taskQueue;
}    

attached() {

}

bind(bindingContext, overridingContext) {
    if (overridingContext.$last === true) {
        this.taskQueue.queueMicroTask(
            () => {
                //This is the jQuery update call to the tablesorter function
                $('#' + this.value).trigger('update');
            }
        );
    }
}

}

【讨论】:

    猜你喜欢
    • 2011-07-17
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 2020-11-23
    • 2020-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多