Twitter Bootstrap typeahead:使用`this`获取上下文/调用元素

时间:2022-03-12 15:52:58

I am using the Typeahead component of Twitter Bootstrap 2.1.1, and jQuery 1.8.1

我正在使用Twitter Bootstrap 2.1.1和jQuery 1.8.1的Typeahead组件

I am trying to access the text box element from within typeahead's updater function. Here is my current code, which works great:

我试图从typeahead的updater函数中访问文本框元素。这是我目前的代码,效果很好:

$('#client-search').typeahead({
    source: function (query, process) {
        $.get(url, { query: query }, function (data) {
            labels = [];
            mapped = {};
            $.each(data, function(i,item) {
                mapped[item.label] = item.value;
                labels.push(item.label);
            });
            process(labels);
        });
    }
    ,updater: function (item) {
        $('#client-id').val(mapped[item]);
        return item;
    }
    ,items: 10
    ,minLength: 2
});

I have many typeahead search boxes on the same page. Each search box has an id #xxx-search and a corresponding hidden input with id #xxx-id. I'd like to re-use the same code for everything by doing something like this:

我在同一页面上有很多类型的搜索框。每个搜索框都有一个id#xxx-search和一个id为#xxx-id的相应隐藏输入。我想通过这样做来重复使用相同的代码:

$('#client-search, #endClient-search, #other-search').typeahead({

    ...

    ,updater: function (item) {
        var target = $(this).attr('id').split('-')[0] + '-id';
        $('#'+target).val(mapped[item]);
        return item;
    }

    ...

I thought that this would refer to the text box element in use, but apparently not, because I get an undefined error in firebug:

我认为这会引用正在使用的文本框元素,但显然不是,因为我在firebug中得到一个未定义的错误:

$(this).attr("id") is undefined

When I use this instead of $(this), I get:

当我使用它代替$(this)时,我得到:

this.attr is not a function

Can anyone help make this work?

谁能帮忙做这个工作?


UPDATE: THE ANSWER, AND MORE!

更新:答案,还有更多!

Thanks to benedict_w's answer below, not only does this work perfectly now, but I have also made this much better in terms of re-usability.

感谢benedict_w在下面的回答,这不仅现在完美无缺,而且在可重用性方面我也做得更好。

Here is what my <input>s look like:

这是我的的样子:

<input type="text" autocomplete="off"
    id="client-search"
    data-typeahead-url="/path/to/json"
    data-typeahead-target="client-id">
<input type="hidden" id="client-id" name="client-id">

Notice how the search box references the hidden id. Here's the new js:

请注意搜索框如何引用隐藏的ID。这是新的js:

$(':input[data-typeahead-url]').each(function(){
    var $this = $(this);
    $this.typeahead({
        source: function (query, process) {
            $.get($this.attr('data-typeahead-url'), { query: query }, function (data) {
                labels = [];
                mapped = {};
                $.each(data, function(i,item) {
                    mapped[item.label] = item.value;
                    labels.push(item.label);
                });
                process(labels);
            });
        }
        ,updater: function (item) {
            $('#'+$this.attr('data-typeahead-target')).val(mapped[item]);
            return item;
        }
        ,items: 10
        ,minLength: 2
    });
});

2 个解决方案

#1


24  

You are inside another function so you need to save a reference to the element in the outer closure, this can then be passed into the event handler of the inner closure. You can do that using an $.each() call to loop through the selector saving a reference to the element (this) each time - e.g.

您在另一个函数内部,因此您需要在外部闭包中保存对该元素的引用,然后可以将其传递到内部闭包的事件处理程序中。你可以使用$ .each()调用来循环选择器,每次都保存对元素(this)的引用 - 例如

$('#client-search, #endClient-search, #other-search').each(function() {
    var $this = $(this);
    $this.typeahead({
        ...

        ,updater: function (item) {
            var target = $this.attr('id').split('-')[0] + '-id';
            $('#'+target).val(mapped[item]);
            return item;
        }
        ...
     });

#2


5  

The accepted answer is a good one, but just wanted to share an alternative that doesn't actually require the outer closure. I'm using bootstrap v2.3.1 and the input is available to you from this.$element.

接受的答案是一个很好的答案,但只是想分享一个实际上不需要外部封闭的替代方案。我正在使用bootstrap v2.3.1并且输入可以从这里获得。$ element。

Eg:

例如:

$(':input[data-typeahead-url]').typeahead({
    source: function (query, process) {
        $.get(this.$element.attr('data-typeahead-url'), { query: query }, function (data) {
            labels = [];
            mapped = {};
            $.each(data, function(i,item) {
                mapped[item.label] = item.value;
                labels.push(item.label);
            });
            process(labels);
        });
    }
    ,updater: function (item) {
        $('#'+this.$element.attr('data-typeahead-target')).val(mapped[item]);
        return item;
    }
    ,items: 10
    ,minLength: 2
});

#1


24  

You are inside another function so you need to save a reference to the element in the outer closure, this can then be passed into the event handler of the inner closure. You can do that using an $.each() call to loop through the selector saving a reference to the element (this) each time - e.g.

您在另一个函数内部,因此您需要在外部闭包中保存对该元素的引用,然后可以将其传递到内部闭包的事件处理程序中。你可以使用$ .each()调用来循环选择器,每次都保存对元素(this)的引用 - 例如

$('#client-search, #endClient-search, #other-search').each(function() {
    var $this = $(this);
    $this.typeahead({
        ...

        ,updater: function (item) {
            var target = $this.attr('id').split('-')[0] + '-id';
            $('#'+target).val(mapped[item]);
            return item;
        }
        ...
     });

#2


5  

The accepted answer is a good one, but just wanted to share an alternative that doesn't actually require the outer closure. I'm using bootstrap v2.3.1 and the input is available to you from this.$element.

接受的答案是一个很好的答案,但只是想分享一个实际上不需要外部封闭的替代方案。我正在使用bootstrap v2.3.1并且输入可以从这里获得。$ element。

Eg:

例如:

$(':input[data-typeahead-url]').typeahead({
    source: function (query, process) {
        $.get(this.$element.attr('data-typeahead-url'), { query: query }, function (data) {
            labels = [];
            mapped = {};
            $.each(data, function(i,item) {
                mapped[item.label] = item.value;
                labels.push(item.label);
            });
            process(labels);
        });
    }
    ,updater: function (item) {
        $('#'+this.$element.attr('data-typeahead-target')).val(mapped[item]);
        return item;
    }
    ,items: 10
    ,minLength: 2
});