以双向数据绑定控件转换回

Convert back in a two way databound control

我正在尝试创建一个可以让用户编辑文件属性的表单。

我想允许用户更改文件的基本名称,但扩展名应保持只读。

我的链接对象有一个 fileName 属性,其中包含包含扩展名的实际文件名。

我的模板使用转换器来拆分文件名部分并在用户编辑字段后重建完整的文件名。

但是,我没有找到将参数传递给我的转换回转换器的方法。具体来说,我不知道如何将扩展传递给 convert back 方法。

这里是一个小复制:

(function($) {
  var getBaseName = function(value) {
    if (!value || (typeof value !== 'string')) return null;
    var lastDot = value.lastIndexOf('.');
    if (lastDot >= 0) {
      return value.substring(0, lastDot);
    }
    return value;
  };
  var getFileExtension = function(value) {
    if (!value || (typeof value !== 'string')) return null;
    var lastDot = value.lastIndexOf('.');
    if (lastDot >= 0) {
      return value.substring(lastDot);
    }
    return null;
  };
  var toFileName = function(value) {
    // how to get the extension here ?
    return value;
  };

  var dataVm = {
    fileName: "somefile.png"
  };
  $.views.converters({
    getBaseName: getBaseName,
    getFileExtension: getFileExtension,
    toFileName: toFileName
  });

  $.templates("#mainTemplate").link("#container", dataVm);
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsviews/0.9.90/jsviews.min.js"></script>


<script id="mainTemplate" type="text/x-jsrender">
  <p>Actual file name :
    <b data-link="fileName"></b></p>
  <br/>

  <input data-link="{getBaseName:fileName:toFileName}" />
  <span data-link="{getFileExtension:fileName}"></span>
</script>

<div id="container">

</div>

特别是,在这一行,<input data-link="{getBaseName:fileName:toFileName}" /> 如何向 toFileName 提供参数?

我尝试了 jsRender pi 的一些语法,但没有成功。

不过,作为一种变通方法,如果我在 dataVm 中保留扩展,我就能让它工作:

  var dataVm = {
    fileName: "somefile.png",
    extension: getFileExtension("somefile.png")
  };

并访问转换器中的上下文:

  var toFileName = function(value) {        
    return value + this.ctx.root.extension;
  };

这确实有效,但它在转换器和数据视图模型之间创建了依赖关系。此外,这不应该适用于网格。最终,转换器应该是不知道其用法的转换器集合的一部分。

转换器的 this 指针是标记实例 - 参见 http://www.jsviews.com/#convertersapi

即使使用 data-link="{cvt:...:cvtBack}",您也有一个 {: ...} 标签的实例。它使您能够通过 this.tagCtxthis.linkCtx 等获取有用的属性。在这里您可以使用 this.tagCtx.args[0] 获取完整的文件名字符串。

更简单,您可以将 fileExtension 存储为标签实例中的 属性:

(function($) {
  var getBaseName = function(value) {
    if (!value || (typeof value !== 'string')) return null;
    var lastDot = value.lastIndexOf('.');
    if (lastDot >= 0) {
      // store fileExtension on tag instance
      this.fileExtension = value.substring(lastDot);
      return value.substring(0, lastDot);
    }
    return value;
  };
  var getFileExtension = function(value) {
    if (!value || (typeof value !== 'string')) return null;
    var lastDot = value.lastIndexOf('.');
    if (lastDot >= 0) {
      return value.substring(lastDot);
    }
    return null;
  };
  var toFileName = function(value) {
    return value + this.fileExtension;
  };

  var dataVm = {
    fileName: "somefile.png"
  };
  $.views.converters({
    getBaseName: getBaseName,
    getFileExtension: getFileExtension,
    toFileName: toFileName
  });

  $.templates("#mainTemplate").link("#container", dataVm);
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsviews/0.9.90/jsviews.min.js"></script>


<script id="mainTemplate" type="text/x-jsrender">
  <p>Actual file name :
    <b data-link="fileName"></b></p>
  <br/>

  <input data-link="{getBaseName:fileName:toFileName}" />
  <span data-link="{getFileExtension:fileName}"></span>
</script>

<div id="container">

</div>