-
Notifications
You must be signed in to change notification settings - Fork 6.7k
feat(): dropdown-toggle rewrite #284
Comments
I forgot to add, there'd be no isolate scope or transclusion happening. |
I've only been following this conversation passively, but I'm hoping to get more involved. My issue here is that it's very Bootstrap-specific. It seems like we would have to rewrite the plugin in order to use something else (e.g. Foundation). |
It's not really, though. If it's desired, the directive could automatically apply I'm not familiar with Foundation and I did some Googling, but I wasn't able to find an example of a dropdown menu using Foundation—can you point me to a specific example? |
Ahh, I found Foundation's docs on it. They do dropdowns strangely—not a fan. Regardless, making it compatible with Foundation probably wouldn't be too much work. The biggest hurdle I can see is getting accurate positioning. That aside, Foundation and Bootstrap do not behave the same way, especially in the case of the split button: Bootstrap's dropdown is positioned relative to parent while Foundation's dropdown is positioned relative to the toggler. That could be reconciled by allowing the user to specify whether they would like the dropdown positioned relative to parent or button. |
UI Bootstrap has a long-term goal to support any framework, which is why we've been trying really hard to ensure none of the components include knowledge of the DOM structure or CSS classes from within the directive (though it's not perfect yet), but instead place all of that in the template. I agree that dropdowns are a tricky case, but I feel we should try to find a solution that doesn't tie us to any framework and would hopefully rely on templates for everything DOM- or style-related. |
The frameworkless path would be the Foundation method of absolutely positioning the dropdown as a direct child of the body elem. The markup in the original post would still work for that path. So then the user would need to configure if they want the dropdown positioned relative to the toggler's parent or the toggler itself--the Bootstrap style or the Foundation style, respectively. |
@angular-ui/bootstrap Why we can't use something like Bootstrap's feaures for the dropdown are keyboard navigation and close on Esc. I think a refactor should address this ones also. |
Good idea, looks like a lot can be borrowed from |
Yeah you're right, it is a lot like popover. Another thing: I think we should have no opinion about what element opens it - we should just have it have a variable for being shown/hidden. Or ... do we need to know something for the sake of positioning? |
@ajoslin I agree with the variable, so that we can programmatically open / close the dropdown. If we follow bootstrap's html I don't think there will be a problem with positioning. |
The toggler and the menu are still linked in that the menu has to be positioned relative to the toggler. Following Bootstrap's HTML as far as including the I'm not sure what you mean @ajoslin when you talk about abstracting it down to a variable—what would the use case be for that? Having many togglers to one menu? How would that relationship be defined? |
@shaungrady I think @ajoslin proposes the Also, the toggler will be used to position the dropdown element. |
@shaungrady yeah, as @bekos said. You could do btn-group like this: <div class="btn-group" ng-class="{toggle: showDropdown}">
<button class="btn">Hello</button>
<button class="btn dropdown-toggle" ng-cilck="showDropdown = !showDropdown">
<span class="caret"></span>
</button>
<!-- compiles to <ul> element -->
<dropdown is-open="showDropdown">
<li ng-repeat="opt in options">{{opt}}</li>
</ul>
</div> It wouldn't even require a new scope - it would just use $parse to set This way allows you to do weird dropdown buttons that aren't sibling elements with their openers. Eg: <div class="things">
<dropdown is-open="showMe">
<li>Option</li>
</dropdown>
</div>
<button class="btn" ng-click="showMe=!showMe">Toggle Dropdown</button> |
So the toggler and menu would be defined separately, and you'd have to give each menu a unique identifier that each toggler would use to reference a dropdown. Sounds fragile, and I'm not sure that use case would be very common. You lose the convenience to defining the dropdown in one place and not having to worry about how it works. A DRY approach of defining one menu to many togglers could be achieved by defining the menu in the scope and referencing it in a toggler attr, or by passing a menu template to the toggler to be compiled with the toggler. |
I think I've got a good idea for how I envision it working—I'll start work on my potential solution when I've got spare time and show it to you guys for feedback. |
You may be right... that non-sibling elements will never be used. But we still don't want to enforce dom structure. Why do we need a unique id for each dropdown? Can't we just let them be positioned as they normally would? |
The "unique ID" in your second example would be |
Ah, you're right. Ok I'm not convinced on my idea. What does everyone else think? |
I am actually starting to like your new syntax... People can use a popover if they want weird stuff like what I'm describing. we don't usually like HTML in attributes though. For your original example, couldn't just have the label be text of the button? <button class="dropdown">
Dropdown Button <span class='caret'></span>
<ul>
<li><a href="#">Do</a></li>
<li><a href="#">Re</a></li>
<li class="divider"></li>
<li><a href="#">Mi</a></li>
</ul>
</button> |
Here's my initial commit, see the commit message for details.Everything's working, but no keydown listener yet. |
Also forgot to mention that, currently, the dropdown menu is absolutely positioned relative to the directive element's parent. I still need to add the option to configure which element the dropdown is positioned relative to—whether the user would like it positioned relative to the parent (bootstrap's behavior) or relative to the toggler (Foundation's behavior). |
.... two months later .... sorry shaun :-) I like your implementation! @shaungrady would you like to open a PR with that commit and tests? If you have moved past this, I can try that. |
Life has kept me quite busy lately, so I haven't done a whole lot more work on this. I've been using a revised form of this directive in my 9-to-5. Having the |
I'm thinking perhaps: <dropdown-menu>
<a class="btn dropdown-toggle" dropdown-toggle ng-model="dropIsOpen">
Dropdown <i class="caret"></i>
</a>
<ul>
<li>Option</li>
<li>Option</li>
</ul>
</dropdown-menu> The The |
oops :-) |
Interesting approach Andy. A couple thoughts: I'm partial to the idea that the menu element be placed as a child of the body—or, at the very least, a child of the nearest offset parent. The concern being that the menu element can interfere with sibling selector styles—e.g., if you have a group of buttons that aren't rounded when placed beside each other, a menu element placed between them would break that style. Additionally, if the menu element is moved to be a direct child of the body it wouldn't have the possibility of being clipped by an Second, I think linking the visibility state of the dropdown to the model should be optional. If you've got tabular data and you need every ngRepeated row to have a dropdown menu associated with it, you're not going to want to assign a model value to each one. |
So dropdown menu could really just be a popover with a different template? :-) |
Any news on dropdown directive ? :-) Currently menu is closed by watching for $location.path() but my menu is located in a scope outside ng-view, |
Closes angular-ui#270 Closes angular-ui#284 Closes angular-ui#1447 Closes angular-ui#1558 feat(dropdown): fix
@bekos @pkozlowski-opensource @ajoslin, here's what I'm thinking about for a refactored
dropdownToggle
directive. First, I'd propose renaming it to simplydropdown
. The markup would be very simple:When the
dropdown
directive is compiled, it would move theul
to the outside of thebutton
(so it's a sibling) and set a style ofdisplay: none
, then theinnerHTML
of thebutton
would be set to thelabel
attr.When the
button
is clicked, theul
will have thedisplay: none
style unset and thebutton
will receive a class ofactive
(could be changed viaactiveclass
attr, or config?)I think this is a simple and flexible solution, and it's all self-contained. The only downside to this approach is that it assumes the dropdown element is wrapped in a relatively positioned element, e.g., a
div.btn-group
.What are your thoughts?
The text was updated successfully, but these errors were encountered: