首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >需要使用触摸屏从AngularJS指令中更新模型

需要使用触摸屏从AngularJS指令中更新模型
EN

Stack Overflow用户
提问于 2015-03-16 06:16:17
回答 1查看 458关注 0票数 0

我使用ng-重复在表单上创建一系列输入字段:

代码语言:javascript
复制
<div class="col-sm-6 input" data-ng-repeat="v in values">
    <div data-prefix-numeric-input data-prefix-name="{{ v.name }}">
        <input type="number" id="{{v.name}}" data-ng-model="form.numberArray[v.name]" data-number-validation />
    </div>
</div>

我使用一些css来隐藏标准的input:type=number旋转器,使用下面的指令创建更适合在触摸屏设备上使用的按钮。

代码语言:javascript
复制
directives.directive('prefixNumericInput', ['$compile', function ($compile) {

    function getInputElement(attrs, element) {
        var inputTagType = attrs['cpNumericInput'].length ? attrs['cpNumericInput'] : 'input';
        return element.find(inputTagType);
    }

    function getInputValue(element) {
        var currentValue = element[0].valueAsNumber;
        return isNaN(currentValue) ? 0 : currentValue;
    }

    return {
        restrict: 'A',
        templateUrl: 'html-templates/numeric-input.html',
        replace: false,
        transclude: true,
        require: '^form',
        scope: {
            prefixName: '@'
        },

        link: function (scope, element, attrs, formController, transcludeFn) {

            transcludeFn(function (clone) {
                var placeholder = element.find('placeholder');
                placeholder.replaceWith(clone);
            });

            var intervalId, inputElement = getInputElement(attrs, element);
            inputElement.addClass('form-control');

            // Add our buttons after the input's parent element
            $(inputElement[0].parentElement).after($compile('<div class="float-right">' +
                '<button type="button" class="btn btn-primary inc-button" data-cp-touchstart="incrementStart()" data-cp-touchend="stop()" data-ng-click="increment()">+</button>' +
                '<button type="button" class="btn btn-primary inc-button" data-cp-touchstart="decrementStart()" data-cp-touchend="stop()" data-ng-click="decrement()">-</button>')(scope));

            function increment() {
                inputElement[0].value = 1 + getInputValue(inputElement);
                scope.$parent.$digest();
            }

            function decrement () {
                var currentValue = getInputValue(inputElement);
                inputElement[0].value = currentValue > 0 ? currentValue - 1 : 0;
            }

            scope.increment = increment;

            scope.decrement = decrement;

            scope.incrementStart = function () {
                increment();
                intervalId = setInterval(increment, 100);
            }

            scope.stop = function () {
                clearInterval(intervalId);
            }

            scope.decrementStart = function () {
                decrement();
                intervalId = setInterval(decrement, 100);
            }
        }
    };
}]);

模板如下:

代码语言:javascript
复制
<div class="input-group">
    <span class="input-group-addon">{{prefixName}}</span>
    <placeholder></placeholder>
</div>

除了一个问题外,这个方法很好用。我们只需要一个输入字段就有一个值。当表单提交时,将运行另一个指令(cf )。以上数字验证)。这只是检查模型值中是否有大于零的输入。如果是这样的话,它将验证所讨论的控件。但是,如果用户使用触摸屏并在页面下进一步增加其中一个字段的值,则每个输入字段到该字段的值都被视为无效。这是因为在实际使用该值到达字段之前,模型值似乎不会被设置。我将模型数组(form.numberArray)转储到验证指令中的控制台,并且可以看到每次运行验证指令时都会追加每个值。

我需要的是让模型更新时,按钮被触摸。我试着使用scope.$parent.$apply,但是只得到了一个‘进行中’错误。

收到的任何意见、指导或建议。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-03-17 22:27:55

这是我想出的解决办法。请注意,在代码中,我使用“前缀”作为占位符,用于区分您的逻辑和AngularJS的前缀。

代码语言:javascript
复制
directives.directive('prefixTouchstart', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.on('touchstart', function (event) {
                scope.$apply(function () {
                    scope.$eval(attrs.prefixTouchstart);
                });
            });
        }
    }
});

directives.directive('prefixTouchend', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.on('touchend', function (event) {
                scope.$apply(function () {
                    scope.$eval(attrs.prefixTouchend);
                });
            });
        }
    }
})

然后使用以下指令创建输入字段。请注意,触摸其中一个按钮并将手指握在那里将逐步增加/减少输入字段。只有当触摸结束事件触发时,模型才会被更新。原因是在更新setInterval逻辑中的模型时,AngularJS没有在UI中反映这些更改,我们不能调用$apply,因为我们只会得到“正在进行”的错误(在touchstart/touchend指令中调用$apply)。请参阅上图)。

代码语言:javascript
复制
directives.directive('prefixNumericInput', ['$compile', function ($compile) {

    return {
        restrict: 'E',
        templateUrl: 'html-templates/numeric-input.html',
        transclude: true,
        scope: {
            prefixName: '@',
            prefixModel: '=',
            prefixPlaceholder: '@'
        },

        link: function (scope, element, attrs, ctrl, transcludeFn) {

            var intervalId, inputElement = element.find('input');
            var currentValue = scope.prefixModel ? scope.prefixModel : 0;
            inputElement.addClass('form-control');

            // Add our buttons after the input's parent element
            $(element).after($compile('<div class="float-right">' +
                '<button type="button" class="btn btn-primary inc-button" data-prefix-touchstart="incrementStart()" data-prefix-touchend="stop()" data-ng-click="increment()">+</button>' +
                '<button type="button" class="btn btn-primary inc-button" data-prefix-touchstart="decrementStart()" data-prefix-touchend="stop()" data-ng-click="decrement()">-</button>')(scope));

            function decrementCurrentValue() {
                if (currentValue > 0) {
                    --currentValue;
                    return true;
                }
                return false;
            }

            function decrement() {
                if (decrementCurrentValue()) {
                    inputElement[0].value = currentValue;
                }
            }

            scope.increment = function() {
                scope.prefixModel = ++currentValue;
            };

            scope.decrement = function() {
                if (decrementCurrentValue()) {
                    scope.prefixModel = currentValue;
                }
            };

            scope.incrementStart = function () {
                inputElement[0].value = ++currentValue;
                intervalId = setInterval(function() {
                    inputElement[0].value = ++currentValue;
                }, 100);
            }

            scope.stop = function () {
                scope.prefixModel = currentValue;
                clearInterval(intervalId);
            }

            scope.decrementStart = function () {
                decrement();
                intervalId = setInterval(decrement, 100);
            }
        }
    };
}]);

以下是html模板:

代码语言:javascript
复制
<div class="input-group column calc-width">
    <span class="input-group-addon">{{prefixName}}</span>
    <input type="number" min="0" id="{{prefixName}}" data-ng-model="prefixModel" placeholder="{{prefixPlaceholder}}" />
</div>

创建字段的代码如下所示:

代码语言:javascript
复制
<div class="col-sm-6 input" data-ng-repeat="value in values">
     <prefix-numeric-input data-prefix-name="{{ value.name }}" data-prefix-model="form.valueArray[value.name]" data-prefix-placeholder="Enter some sort of value here"></prefix-numeric-input>
</div>

我们使用Bootstrap,因此css类散落在整个逻辑中。希望这能帮到别人。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29070627

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档