如何修改 AngularJS Bootstrap 下拉菜单/select 使其不使用 jQuery?
How can I modify an AngularJS Bootstrap dropdown / select so that it does not use jQuery?
我看到了 AngularJS Bootstrap 类型 Select 指令的一个很好的例子:
http://jsfiddle.net/cojahmetov/3DS49/
这满足了我的大部分需求,但它使用了 jQuery 而我们没有使用该库。
此示例中使用的 jQuery 非常少,但我不知道如何替换如下所示的元素定位器:
谁能给我任何关于如何替换它的指示:
switch (attrs.menuType) {
case "button":
$('button.button-label', element).html(item.name);
break;
default:
$('a.dropdown-toggle', element).html('<b class="caret"></b> ' + item.name);
break;
}
这样它就可以在没有 jQuery
的情况下工作?理想情况下,我希望有人知道得足够多,可以根据 ui-bootstrap
中的版本提出一个版本。也许这甚至可以添加到 ui-bootstrap 供其他人使用。
Edit:我是对的,您不需要在此示例中使用 .html(),这通常是一种不好的做法。请注意我是如何使用 scope
对象来实现相同结果的:http://jsfiddle.net/3DS49/162/
对于您在此处显示的最小示例,您可以使用 angular.element
而不是 $
或 jQuery
。 angular.element
是一个子集,但它支持 .html().
但是,这仍然是一个不好的做法,因为内容可以放在 scope
中,而 html 内容可以设置为按钮模板中的直接绑定。
编辑: angular.element 不支持选择器。您应该为此使用本机方法(getElementById 及其朋友)。但是,请确保您没有使用 jquery 特定的选择器,例如 :first。例如:
var elements = document.querySelectorAll(".myclass");
//it is up to you to iterate over the elements and call angular.element(element).html(yourValueHere) on each element.
//NOTE: you can get document from $windowProvider.$get().document, or $window.document, depending on the place (you will use $window.document in this case).
编辑:检查浏览器支持 here - 没有支持选择器的本机 angular 方式。
对于特定案例的实际实施,可以安全地查看@ChrisFrank 的回答。但是,请记住,您可以使用 angular.element
函数包装每个迭代的元素(例如在他的回答中)以获得 jqLite(AngularJS 的内置子集 jQuery - 你不需要需要任何额外的库)对象。
此方案只支持IE9+,如果你需要支持旧版浏览器,我可以找到其他方案并更新。
http://jsfiddle.net/3DS49/160/
scope.selectVal = function (item) {
function selector(sel, htmlCont)
{
var elems = document.querySelectorAll(sel);
Array.prototype.forEach.call(elems, function(el, i){
el.innerHTML = htmlCont;
});
}
switch (attrs.menuType) {
case "button":
selector('button.button-label', item.name);
break;
default:
selector('a.dropdown-toggle', '<b class="caret"></b> ' + item.name);
break;
}
scope.doSelect({
selectedVal: item.id
});
};
Fiddle 的想法很好,但我发现实现有点混乱。那么一个人能做什么呢?好吧,当然,在 ui-bootstrap
之上写一个替代的 dropdown
指令!
希望这对您有所帮助。应该很好用。
用法
<dropdown is-button
ng-model="vm.item"
items="vm.items"
callback="vm.callback(item)">
</dropdown>
所以你传入 ng-model
保存初始选择,如果有的话。新值是从指令中设置的。在 items
中,您有 id-name
对集合可供选择,如果需要,还可以使用 callback
函数。如果您指定 is-button
属性,您将获得按钮式下拉控件。
然后控制器可能如下所示。
控制器
// Controller
app.controller('Ctrl', function() {
var vm = this;
// items collection
vm.items = [{
id: 0,
name: 'London'
},{
id: 1,
name: 'Paris'
},{
id: 2,
name: 'Milan'
}];
// current item
vm.item = null; // vm.items[1];
// directive callback function
vm.callback = function(item) {
vm.fromCallback = 'User selected ' + angular.toJson(item);
};
});
dropdown
指令的逻辑非常简单,真的。
指令javaScript
// Dropdown directive
app.directive('dropdown', function() {
return {
restrict: 'E',
require: '^ngModel',
scope: {
ngModel: '=', // selection
items: '=', // items to select from
callback: '&' // callback
},
link: function(scope, element, attrs) {
element.on('click', function(event) {
event.preventDefault();
});
scope.default = 'Please select item';
scope.isButton = 'isButton' in attrs;
// selection changed handler
scope.select = function(item) {
scope.ngModel = item;
if (scope.callback) {
scope.callback({ item: item });
}
};
},
templateUrl: 'dropdown-template.html'
};
});
指令HTML模板
<div class="btn-group" dropdown>
<!-- button style dropdown -->
<button ng-if="isButton"
type="button"
class="btn btn-primary"
ng-bind="ngModel.name || default">
</button>
<button ng-if="isButton"
type="button"
class="btn btn-primary dropdown-toggle"
dropdown-toggle>
<span class="caret"></span>
</button>
<!-- no button, plz -->
<a ng-if="!isButton"
class="dropdown-toggle"
dropdown-toggle href
ng-bind="ngModel.name || default">
</a>
<span ng-if="!isButton" class="caret"></span>
<!-- dropdown items -->
<ul class="dropdown-menu" role="menu">
<li ng-repeat="item in items">
<a href="#"
ng-bind="item.name"
ng-click="select(item)"></a>
</li>
</ul>
</div>
这是初始实施的外观。除了您提供的示例之外,您还将取回整个对象,而不仅仅是 id
.
此处的相关 Plunker http://plnkr.co/edit/bLWabx 使用 angularjs 1.4.0-beta.3 和 ui-bootstrap 0.12.0.
我看到了 AngularJS Bootstrap 类型 Select 指令的一个很好的例子:
http://jsfiddle.net/cojahmetov/3DS49/
这满足了我的大部分需求,但它使用了 jQuery 而我们没有使用该库。
此示例中使用的 jQuery 非常少,但我不知道如何替换如下所示的元素定位器:
谁能给我任何关于如何替换它的指示:
switch (attrs.menuType) {
case "button":
$('button.button-label', element).html(item.name);
break;
default:
$('a.dropdown-toggle', element).html('<b class="caret"></b> ' + item.name);
break;
}
这样它就可以在没有 jQuery
的情况下工作?理想情况下,我希望有人知道得足够多,可以根据 ui-bootstrap
中的版本提出一个版本。也许这甚至可以添加到 ui-bootstrap 供其他人使用。
Edit:我是对的,您不需要在此示例中使用 .html(),这通常是一种不好的做法。请注意我是如何使用 scope
对象来实现相同结果的:http://jsfiddle.net/3DS49/162/
对于您在此处显示的最小示例,您可以使用 angular.element
而不是 $
或 jQuery
。 angular.element
是一个子集,但它支持 .html().
但是,这仍然是一个不好的做法,因为内容可以放在 scope
中,而 html 内容可以设置为按钮模板中的直接绑定。
编辑: angular.element 不支持选择器。您应该为此使用本机方法(getElementById 及其朋友)。但是,请确保您没有使用 jquery 特定的选择器,例如 :first。例如:
var elements = document.querySelectorAll(".myclass");
//it is up to you to iterate over the elements and call angular.element(element).html(yourValueHere) on each element.
//NOTE: you can get document from $windowProvider.$get().document, or $window.document, depending on the place (you will use $window.document in this case).
编辑:检查浏览器支持 here - 没有支持选择器的本机 angular 方式。
对于特定案例的实际实施,可以安全地查看@ChrisFrank 的回答。但是,请记住,您可以使用 angular.element
函数包装每个迭代的元素(例如在他的回答中)以获得 jqLite(AngularJS 的内置子集 jQuery - 你不需要需要任何额外的库)对象。
此方案只支持IE9+,如果你需要支持旧版浏览器,我可以找到其他方案并更新。
http://jsfiddle.net/3DS49/160/
scope.selectVal = function (item) {
function selector(sel, htmlCont)
{
var elems = document.querySelectorAll(sel);
Array.prototype.forEach.call(elems, function(el, i){
el.innerHTML = htmlCont;
});
}
switch (attrs.menuType) {
case "button":
selector('button.button-label', item.name);
break;
default:
selector('a.dropdown-toggle', '<b class="caret"></b> ' + item.name);
break;
}
scope.doSelect({
selectedVal: item.id
});
};
Fiddle 的想法很好,但我发现实现有点混乱。那么一个人能做什么呢?好吧,当然,在 ui-bootstrap
之上写一个替代的 dropdown
指令!
希望这对您有所帮助。应该很好用。
用法
<dropdown is-button
ng-model="vm.item"
items="vm.items"
callback="vm.callback(item)">
</dropdown>
所以你传入 ng-model
保存初始选择,如果有的话。新值是从指令中设置的。在 items
中,您有 id-name
对集合可供选择,如果需要,还可以使用 callback
函数。如果您指定 is-button
属性,您将获得按钮式下拉控件。
然后控制器可能如下所示。
控制器
// Controller
app.controller('Ctrl', function() {
var vm = this;
// items collection
vm.items = [{
id: 0,
name: 'London'
},{
id: 1,
name: 'Paris'
},{
id: 2,
name: 'Milan'
}];
// current item
vm.item = null; // vm.items[1];
// directive callback function
vm.callback = function(item) {
vm.fromCallback = 'User selected ' + angular.toJson(item);
};
});
dropdown
指令的逻辑非常简单,真的。
指令javaScript
// Dropdown directive
app.directive('dropdown', function() {
return {
restrict: 'E',
require: '^ngModel',
scope: {
ngModel: '=', // selection
items: '=', // items to select from
callback: '&' // callback
},
link: function(scope, element, attrs) {
element.on('click', function(event) {
event.preventDefault();
});
scope.default = 'Please select item';
scope.isButton = 'isButton' in attrs;
// selection changed handler
scope.select = function(item) {
scope.ngModel = item;
if (scope.callback) {
scope.callback({ item: item });
}
};
},
templateUrl: 'dropdown-template.html'
};
});
指令HTML模板
<div class="btn-group" dropdown>
<!-- button style dropdown -->
<button ng-if="isButton"
type="button"
class="btn btn-primary"
ng-bind="ngModel.name || default">
</button>
<button ng-if="isButton"
type="button"
class="btn btn-primary dropdown-toggle"
dropdown-toggle>
<span class="caret"></span>
</button>
<!-- no button, plz -->
<a ng-if="!isButton"
class="dropdown-toggle"
dropdown-toggle href
ng-bind="ngModel.name || default">
</a>
<span ng-if="!isButton" class="caret"></span>
<!-- dropdown items -->
<ul class="dropdown-menu" role="menu">
<li ng-repeat="item in items">
<a href="#"
ng-bind="item.name"
ng-click="select(item)"></a>
</li>
</ul>
</div>
这是初始实施的外观。除了您提供的示例之外,您还将取回整个对象,而不仅仅是 id
.
此处的相关 Plunker http://plnkr.co/edit/bLWabx 使用 angularjs 1.4.0-beta.3 和 ui-bootstrap 0.12.0.