在 angularjs 中集成 bootstrap typeahead

問題

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

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

typeahead 中選擇數據以後的事件 itemSelected

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

這個函數的使用方式以下:服務器

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

集成到頁面中,咱們能夠以下配置 typeahead 的配置參數。app

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 天然就能夠感知到數據的變化了。post

實現

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

指令的定義以下:url

// 自定義指令
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 天然就能夠獲取數據的變化了。spa

元素的定義以下,增長一個名爲 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 之中。

相關文章
相關標籤/搜索