问题
I'm trying to implement a dropdown box to show search options, much the way the Stack Overflow tag search box works. The search itself is working great, but I can't get the box to show up at the right times.
Here's the template:
<div class="dropdown">
<input class="entryInput" id="query" name="query" type="text"
data-toggle="dropdown"/>
<ul class="dropdown-menu" role="menu" aria-labelledby="query">
{{#each queryResults}}
<li><a class="result" data-id="{{_id}}">{{firstname}}</a></li>
{{/each}}
</ul>
</div>
This code works, and the list displays in the dropdown, but it displays an empty stub when the input is first clicked (see my screencap to see what that empty stub looks like), and disappears when I begin typing.
Elsewhere in my app, I manage Session.get('query')
and Session.get('queryPopulated')
, which are the values I want this dropdown to react to. query
is simply storing the query itself in real-time, and queryPopulated
is a boolean that is set when the user chooses a result. I want the dropdown to stay active as long as these things are true:
- the input has focus;
- the
query
is valid (so no showing a lame stub); - and
queryPopulated
is false (because there's no more reason to display, the user chose a result).
The Bootstrap docs only provide a toggle
method, and that just isn't really fine-grained enough. I need to manually take control of the dropdown's reactions, and I'm not sure how to do that with the events and methods it's exposed.
How do I override the behavior?
Here's what that lame stub looks like.

Thanks in advance!
Update
I now have this javascript managing the dropdown:
Template.entryStudentInput.rendered = function() {
$('.dropdown').on('shown.bs.dropdown', function(){
console.log('show');
if(!Session.get('query')) {
console.log('query is false in show');
$('.dropdown').dropdown('toggle');
}
});
};
That block above successfully prevents the dropdown from showing when empty, but I can't get the dropdown to show again once the query is valid.
Here's another block, meant only as an experiment, reacting to key events:
Template.entryStudentInput.events({
'keyup #query': function(e, t) {
console.log('should toggle');
$('dropdown').dropdown('toggle');
// These didn't work either.
// $(t.find('.dropdown')).dropdown('toggle');
// t.find('.dropdown').dropdown('toggle');
}
});
It should simply toggle back and forth every time a key is pressed, but it doesn't do anything at all. The console
log shows up just like it should, but there's no change whatsoever on the dropdown. It seems like I just have no control over the dropdown from anywhere but the $('.dropdown').on
event handlers.
回答1:
You just have to reverse toggle effect of your ul
when it doesn't have children.
Exemple with 2 dropdowns, 1 with and 1 without children.
Bootply : http://www.bootply.com/120571
JS :
$('.dropdown').on('shown.bs.dropdown', function(){
if( $(this).find('.dropdown-menu').children().length == 0)
{
$(this).dropdown('toggle');
}
});
HTML :
<div class="col-md-6">
<div class="dropdown">
<input class="entryInput" id="query" name="query" type="text" data-toggle="dropdown">
<ul class="dropdown-menu" role="menu" aria-labelledby="query">
<li><a class="result" data-id="{{_id}}">{{firstname}}</a></li>
<li><a class="result" data-id="{{_id}}">{{firstname}}</a></li>
<li><a class="result" data-id="{{_id}}">{{firstname}}</a></li>
<li><a class="result" data-id="{{_id}}">{{firstname}}</a></li>
<li><a class="result" data-id="{{_id}}">{{firstname}}</a></li>
<li><a class="result" data-id="{{_id}}">{{firstname}}</a></li>
</ul>
</div>
</div>
UPDATE :
To achieve what you want so, a better method is to affect the hidden
class when no children, and remove this class when your query populate it.
Bootply : http://www.bootply.com/120667
As you can see in this exemple [ a setTimeout is running to emulate your achieved query] , when the first ul
don't have children, nothing append, and when this ul
is populated, the dropdown appear.
JS:
$('.dropdown').on('shown.bs.dropdown', function(e){
if( $(this).find('.dropdown-menu').children().length == 0)
{
$(this).find('.dropdown-menu').addClass('hidden');
}
});
setTimeout(function(){
$('.dropdown').first().find('.dropdown-menu').append($('.dropdown').last().find('.dropdown-menu').html());
$('.dropdown').first().find('.dropdown-menu').removeClass('hidden');
alert('5s elapsed');
}, 5000);
回答2:
I found it was cleaner to abandon the dropdown box entirely. It didn't fit my needs. I instead have just created a list-group
that appears/reappears as the query changes.
<div class="input-group">
<input class="entryInput form-control" id="query" name="query" type="text"
{{#if session "queryPopulated"}}readonly{{/if}}/>
<span class="input-group-btn">
<button id="cancelQuery" class="btn btn-default" type="button"
{{#unless session "queryPopulated"}}disabled{{/unless}}>
<span class="glyphicon glyphicon-remove">
</button>
</span>
</div>
<div class="list-group" {{#unless queryShow}}hidden{{/unless}}>
{{#each queryResults}}
<a href="#" class="result list-group-item" data-id="{{_id}}">{{firstname}} {{lastname}}</a>
{{else}}
<a href="#" class="list-group-item">There are no results for that search.</a>
{{/each}}
</div>
The queryShow
helper is implemented like this:
Template.entryStudentInput.queryShow = function() {
return Session.get('query') && !Session.get('queryPopulated');
};
This works great, although it does push content it downwards. I personally don't care.
来源:https://stackoverflow.com/questions/22285537/bootstrap-input-dropdown-change-activation-behavior