在 angularjs 中集成 bootstrap typeahead


問題

在使用 typeahead 的時候,有這樣一個需求,當用戶選中其中一項的之后,將項目對應的 id 保存到另外一個變量中,以后在提交表單的時候,將這個 id 發送到服務器中。

但是,在 typeahead 中對於元素的操作,angularjs 沒有感知到,導致不能獲取最新的數據。

typeahead 中選擇數據之后的事件 itemSelected

在 typeahead 中,我們可以定義一個 itemSelected 的事件處理函數,在選中一個項目之后, typeahead 會觸發這個事件,我們在這個事件中可以獲取當前選中的元素,對應的值,已經顯示的提示文本。

這個函數的使用方式如下:

itemSelected: function (item, val, text) {
        console.info(val);
}

集成到頁面中,我們可以如下配置 typeahead 的配置參數。

var option = {
    ajax: {
        url: '@Url.Action("AjaxService")',
        timeout: 300,
        method: "post",
        triggerLength: 3,
        preDispatch: function (query) {
            return { type: type, query: query };
        },
        preProcess: function (data) {
            return data;
        }
    },
    display: "name",
    val: "id",
    itemSelected: function (item, val, text) {
        console.info(item);
    }
};
$("#tbxName").typeahead(option);

但是,在使用 angularjs 的時候,會帶來一個問題,如果我們直接將這個 id 賦予某個元素,比如說輸入框的話,angularjs 是不能檢測到這個元素值的變化的,angularjs 通過監測元素的獲取焦點,失去焦點,change 等事件來感知輸入元素的變化,在通過代碼直接賦值的時候,會沒有這些事件的觸發。

原理

我們可以通過 angularjs 的自定義指令將 typeahead 封裝一下,在 itemSelected 事件觸發的時候,調用 angularjs 的 $apply 發出通知,這樣 angularjs 自然就可以感知到數據的變化了。

實現

為了便於已經熟悉 typeahead 的朋友,繼續使用原來的方式進行配置,我們不修改配置方式。

指令的定義如下:

// 自定義指令
app.directive("typeahead", function () {
    var option = {
        restrict: "A",
        require: "?ngModel",
        scope:  {
            option: "=typeahead"
        },
        link: function (scope, element, attrs, ngModel) {

            // typeahead 的配置參數
            var option = scope.option;

            // 將原來的 itemSelected 替換為 angularjs 的 itemSelected 函數
            // 在用戶選擇了選項之后,通過 angularjs 執行
            var itemSelected = option.itemSelected;
            option.itemSelected = function (item, val, text) {
                scope.$apply(function () {
                    itemSelected(item, val, text);
                })
            };

            element.typeahead(option);
        }
    };
    return option;
});

scope 是自定義一個作用域,=typeahead 是將 typeahead 屬性的值取過來,剩下的處理就比較簡單了,我們將原來的 itemSelected 事件截獲過來,通過 scope.$apply 進行處理,這樣 angularjs 自然就可以獲取數據的變化了。

元素的定義如下,增加一個名為 typeahead 的 Attribute, 值就是配置參數對象,定義在 angularjs 的模型對象上。

<input typeahead ="typeaheadOption" ng-model="petName" type="text" />

下面是對應的腳本。

// 控制器
app.controller("myController", function ($scope) {
// 額外附加的參數
    $scope.type = "java";

    // 標准的使用方式
    $scope.petName = "Cat";
    $scope.petId = "";

    // 使用標准的 typeahead 配置參數, 在元素上使用 typeahead Attribute 連接
    $scope.typeaheadOption
        = {
            ajax: {
                url: '@Url.Action("AjaxService")',
                timeout: 300,
                method: "post",
                triggerLength: 3,
                preDispatch: function (query) {
                    return { type: $scope.type, query: query };
                },
                preProcess: function (data) {
                    return data;
                }
            },
            display: "name",
            val: "id",
            itemSelected: function (item, val, text) {
                $scope.petId = val;
            }
        };

});

總結

使用 angularjs 的自定義指令,我們可以很容易地將 angularjs 之外的事件處理封裝到 angularjs 之中。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM