如何防止用户形式忽略angularjs angular-ui-bootstrap uib-typeahead中的建议

时间:2017-12-18 12:24:59

标签: javascript angularjs angular-ui-bootstrap angular-ui-typeahead

我正在使用AngularJS v1.6.6和angular-ui-bootstrap版本:2.5.0来创建自动完成字段。

一切正常但我需要一种方法来确保用户实际从建议列表中选择该选项。

这是我的代码:

HTML:

<div class='container-fluid typeahead-demo' ng-controller="TypeaheadCtrl">
<h4>How to prevent user from typing the whole word ignoring suggestions?</h4>
<div>Model: 
<pre>{{selected | json}}</pre>
</div>
<form role="form" name="chooseStateForm" autocomplete="off" novalidate>
    <div class="form-group required">
        <div>
            <label for="state" class="control-label col-sm-3">Choose a State:</label>
                <input type="text" 
                        class="form-control" 
                        required 
                        placeholder="Try typing the whole name of the state ignoring suggestion" 
                        name="state" 
                        ng-model="selected" 
                        uib-typeahead="option as option.name for option in states | filter:{name: $viewValue}" 
                        typeahead-min-length="1" 
                        typeahead-no-results="noresults" 
                        typeahead-show-hint="true" 
                        >
        </div>
        <div ng-if="noresults">
        <p>No match found!</p>
        </div>
    </div>
</form>
<br><br><br><br>
<div>
    <button class="btn btn-primary" type="button" ng-click="$ctrl.ok()" ng-disabled="chooseStateForm.$invalid">OK</button>
    <button class="btn btn-primary" type="button" ng-click="$ctrl.cancel()">Cancel</button>
</div>

JS:

angular.module('app', ['ui.bootstrap']);
angular.module('app').controller('TypeaheadCtrl', function($scope) {

$scope.selected = undefined;
$scope.states = [
{id: 1, name: 'Alabama'},  
{id: 2, name: 'California'}, 
{id: 3, name: 'Delaware'}, 
{id: 4, name: 'Florida'}, 
{id: 5, name: 'Georgia'}, 
{id: 6, name: 'Hawaii'}, 
{id: 7, name: 'Idaho'},  
{id: 8, name: 'Kansas'}, 
{id: 9, name: 'Louisiana'}, 
{id: 10, name: 'Maine'}, 
{id: 11, name: 'Nebraska'}, 
{id: 12, name: 'Ohio'}, 
{id: 13, name: 'Pennsylvania'}, 
{id: 14, name: 'Rhode Island'}, 
{id: 15, name: 'South Carolina'}, 
{id: 16, name: 'Tennessee'},
{id: 17, name: 'Utah'}, 
{id: 18, name: 'Vermont'}, 
{id: 19, name: 'Washington'}
];
});

看到这个jsfiddle,你会理解我的意思:http://jsfiddle.net/elenat82/yhpbdvva/20/

例如,如果用户想要选择俄亥俄州,因为它只有4个字母,他可以更容易地输入“俄亥俄州”而不是选择建议的选项。

但是这样做我的模型变成了一个字符串,如果他从建议列表中选择它就是一个对象。

是的,我在我的控制器中检查模型的有效性,但我希望在用户提交表单之前完成,我想显示一条错误消息,向用户解释他做错了什么。

----------编辑----------

我找到了另一种方法来实现相同的结果但使用指令并扩展$ validators对象。

以下是更新后的jsfiddle的链接:http://jsfiddle.net/elenat82/fL5fw1up/2/

这是更新后的代码:

HTML:

<div class='container-fluid typeahead-demo' ng-controller="TypeaheadCtrl">
<h4>How to prevent user from typing the whole word ignoring suggestions?</h4>
<div>Model: 
<pre>{{selected | json}}</pre>
<div>Errors: 
<pre>{{chooseStateForm.state.$error | json}}</pre>
</div>
<form role="form" name="chooseStateForm" autocomplete="off" novalidate>
    <div class="form-group required">
        <div>
            <label for="state" class="control-label col-sm-3">Choose a State:</label>
                <input type="text" 
                        class="form-control" 
                        required 
                        placeholder="Try typing the whole name of the state ignoring suggestion" 
                        name="state" 
                        ng-model="selected" 
                        uib-typeahead="option as option.name for option in states | filter:{name: $viewValue}" 
                        typeahead-min-length="1" 
                        typeahead-no-results="noresults" 
                        typeahead-show-hint="true" 
                        object
                        >
        </div>
        <div ng-if="noresults">
        <p>No match found!</p>
        </div>
    </div>
</form>
<br><br><br><br>
<div>
    <button class="btn btn-primary" type="button" ng-click="$ctrl.ok()" ng-disabled="chooseStateForm.$invalid">OK</button>
    <button class="btn btn-primary" type="button" ng-click="$ctrl.cancel()">Cancel</button>
</div>

JS:

angular.module('app', ['ui.bootstrap']);
angular.module('app').controller('TypeaheadCtrl', function($scope) {

$scope.selected = undefined;
$scope.states = [
{id: 1, name: 'Alabama'},  
{id: 2, name: 'California'}, 
{id: 3, name: 'Delaware'}, 
{id: 4, name: 'Florida'}, 
{id: 5, name: 'Georgia'}, 
{id: 6, name: 'Hawaii'}, 
{id: 7, name: 'Idaho'},  
{id: 8, name: 'Kansas'}, 
{id: 9, name: 'Louisiana'}, 
{id: 10, name: 'Maine'}, 
{id: 11, name: 'Nebraska'}, 
{id: 12, name: 'Ohio'}, 
{id: 13, name: 'Pennsylvania'}, 
{id: 14, name: 'Rhode Island'}, 
{id: 15, name: 'South Carolina'}, 
{id: 16, name: 'Tennessee'},
{id: 17, name: 'Utah'}, 
{id: 18, name: 'Vermont'}, 
{id: 19, name: 'Washington'}
];
});


angular.module('app').directive('object', [function() {
return {
    restrict: 'A',
    scope: {},
    require: 'ngModel',
    link: function (scope, element, attrs, ngModel) {

        ngModel.$validators.object = function(modelValue,viewValue){
            if (angular.isObject(modelValue)) {
                return true;
            }
            else {
                return false;
            }
          };
    }
};

}
]);

3 个答案:

答案 0 :(得分:1)

您可以为此验证添加方法,例如:

$scope.isSelected = function() {
    return typeof $scope.selected == "object";
}

答案 1 :(得分:1)

有一个名为typeahead-editable="false"的属性。 如果将其设置为false,则不允许用户“不”&#34;选择一些东西,文本框将设置为空。

链接:https://angular-ui.github.io/bootstrap/#!#typeahead

  

typeahead-editable $(默认值:true) - 是否应该将模型值限制为仅从弹出窗口中选择的值?

http://jsfiddle.net/yhpbdvva/25/

答案 2 :(得分:0)

您需要遍历阵列并检查该阵列上是否存在所选值(ngModel)。您可以定义此类函数并使用ngChange调用它,该值将在您更改值时运行

<input type="text" 
     class="form-control" 
     required
     name="state" 
     ng-model="selected" 
     .....
     ng-change="testIncluded(selected)">

在控制器内部,执行类似的操作(使用Array.prototype.find

$scope.testIncluded = function(value) {
    let isSelectedFromStates = $scope.states.find((state) => {
        return state.name === value;
    })
    /// do something ...
}

如果名称存在,isSelectedFromStates将不会被定义