自定义绑定未按预期工作

时间:2017-09-27 17:52:39

标签: javascript html knockout.js data-binding

我有一个textarea元素,其中包含style属性的特定属性 - > overflow:hidden; resize:none和height:20px。在这种情况下,当我在多行上有一个长文本时,我的textarea将只显示第一行。我的想法是,当我点击它时,我想让它调整大小,整个文本都是可见的。我正在使用Knockout JS,我无法意识到我的绑定有什么问题。

function TextAreaVM() {
    this.active = ko.observable(false);
    
    this.text = ko.observable("Something\nnew line\nanother new line");

    this.setActive = function(){
        this.active(true);
    };

    this.notActive = function(){
        this.active(false);
    };

    ko.bindingHandlers.maximize ={
        update: function(element,valueAccessor){
            element.style.height = element.style.scroolHeight + "px";
        }
    };

    ko.bindingHandlers.minimize={
        update: function(element,valueAccessor){
            element.style.height = "20px";
        }
    };

}

ko.applyBindings(new TextAreaVM());
#txtarea-id{
    resize: none;
    overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<!DOCTYPE html>
<html>
<head>
<style>
</style>
</head>
<body>
<textarea id="txtarea-id" class="txtarea-class" height="20px" 
            data-bind="text: text, 
            event: {focus: setActive, blur: notActive},
            maximize: (active() == true),
            minimize: (active() == false)"
            readonly="true"></textarea>
<textarea id="txtarea-second" class="txtarea-class" height="20px" 
            width="50px" readonly="true">This is the first line and it should appear only on the first row&#13;&#10;This line shuld appera only o the second row!</textarea>
</body>
</html>

我还尝试了element.style.scroolHeight.toString()data-bind="maximize: active(), minimize: !active()"之类的内容,但都没有。此外,我100%确定我的布尔“活动”正常工作(我尝试使用Chrome调试,它表现我想要的方式 - &gt;当我点击textarea时它是真的,当我点击外面它是假的。)< / p>

2 个答案:

答案 0 :(得分:1)

我不是淘汰赛的专家,但你要定义两次:

ko.bindingHandlers.maximize ={
    update: function(element,valueAccessor){
        element.style.height = "20px";
    }
};

意味着只考虑最后一个(这个是最后一个)。

答案 1 :(得分:1)

代码只有三个小问题:

  1. 在您的问题中,您有两个名为maximize的绑定。将其中一个重命名为minimize以避免冲突。

  2. 在绑定处理程序中,在设置元素高度之前,您没有验证valueAccessor的值。因此,每次active可观察的更改时,都会触发绑定处理程序。因此,名为last的处理程序将覆盖前一个处理程序的结果。所以你永远不会看到高度变化。

  3. scroolHeight中有拼写错误。它应该是element.scrollHeight

  4. &#13;
    &#13;
    ko.bindingHandlers.maximize = {
      update: function(element, valueAccessor) {
        if(valueAccessor()) {
         element.style.height = element.scrollHeight + "px";
        }
      }
    };
    
    ko.bindingHandlers.minimize = {
      update: function(element, valueAccessor) {
        if(valueAccessor()) {
          element.style.height = "20px";
        }
      }
    };
    
    function TextAreaVM() {
      this.active = ko.observable(false);
    
      this.text = ko.observable("Something\nnew line\nanother new line");
    
      this.setActive = function() {
        this.active(true);
      };
    
      this.notActive = function() {
        this.active(false);
      };
    }
    
    ko.applyBindings(new TextAreaVM());
    &#13;
    #txtarea-id {
      resize: none;
      overflow: hidden;
    }
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    <!DOCTYPE html>
    <html>
    
    <head>
      <style>
    
      </style>
    </head>
    
    <body>
      <textarea id="txtarea-id" class="txtarea-class" height="20px" data-bind="text: text, 
                event: {focus: setActive, blur: notActive},
                maximize: (active() == true),
                minimize: (active() == false)" readonly="true"></textarea>
    </body>
    
    </html>
    &#13;
    &#13;
    &#13;

    更新

    当您对多个元素使用单个绑定时,您必须验证该元素是具有焦点的元素。因此,将element === document.activeElement添加到if条件就足够了。我已经更新了代码片段,对代码进行了细微更改(在评论中发布),以显示它是如何工作的。

    &#13;
    &#13;
    ko.bindingHandlers.resize = {
      update: function(element, valueAccessor) {
        if (valueAccessor() && element === document.activeElement) {
          element.style.height = element.scrollHeight + "px";
        } else {
          element.style.height = "20px";
        }
      }
    };
    
    function TextAreaVM() {
      this.active = ko.observable(false);
    
      this.text = ko.observable("Something\nnew line\nanother new line");
    
      this.setActive = function() {
        this.active(true);
      };
    
      this.notActive = function() {
        this.active(false);
      };
    }
    
    ko.applyBindings(new TextAreaVM());
    &#13;
    .txtarea-class {
      resize: none;
      overflow: hidden;
    }
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    <!DOCTYPE html>
    <html>
    
    <head>
      <style>
    
      </style>
    </head>
    
    <body>
      <textarea id="txtarea-id" class="txtarea-class" height="20px" data-bind="text: text, 
                event: {focus: setActive, blur: notActive},
                resize: active()" readonly="true"></textarea>
                
    
      <br/>
      <textarea id="txtarea-id2" class="txtarea-class" height="20px" data-bind="text: text, 
                event: {focus: setActive, blur: notActive},
                resize: active()" readonly="true"></textarea>
    </body>
    
    </html>
    &#13;
    &#13;
    &#13;