背景
我正在使用 Angular Material 进行自定义自动完成,我想将自动完成下拉结果框的高度设置为更大的值。
研究
为了实现这一点,我做了一个研究并得出结论,Angular Material 不支持这个,并且这个问题只会在 Angular Material 2(为 AngularJS2 发布)中解决:
- https://github.com/angular/material/issues/5132 (可能的修复 1)
- https://github.com/angular/material/issues/4772 (可能的修复 2)
- https://github.com/angular/material/pull/8397 (最后一篇文章解释说这个问题不会被修复)
- https://groups.google.com/forum/#!topic/ngmaterial/4ActiQp3nA0 (解释 Angular Material 2 和 Angular Material 的弃用)
阅读后,我意识到有些人找到了绕过这种强制 CSS 限制的方法 (Angular Material Design Layout custom sizes),但无论我如何尝试,我都看不到他们的任何建议都能奏效。
代码
我的示例应用程序由一个 index.html
、一个 autocomplete.js
文件和一个带有 mockData 的 server.js
文件组成.json 文件。
以下是index.html
、autocomplete.js
和style.css
文件。由于我在 Cloud9 中托管此示例,如果服务器处于开启状态,您可以看到它实时运行!
/*global angular*/
"use strict";
angular.module('MyApp', ['ngMaterial', 'ngMessages', 'material.svgAssetsCache', 'ngMdIcons']).controller('DemoCtrl', DemoCtrl);
function DemoCtrl($q, $log, $http) {
this.searchText = null;
this.querySearch = function(query) {
let serverUrl = '//custom-material-autocomplete-fl4m3ph03n1x.c9users.io/getClients';
let deferred = $q.defer();
$http({
method: 'GET',
url: serverUrl,
params: {
word: query
}
}).then(function successCallback(response) {
deferred.resolve(response.data);
}, function errorCallback(response) {
$log.error(response);
});
return deferred.promise;
};
this.searchTextChange = function(text) {
$log.info('Text changed to ' + text);
}
this.selectedItemChange = function(item) {
$log.info('Item changed to ' + JSON.stringify(item));
}
}
.autocompletedemoCustomTemplate .autocomplete-custom-template li {
border-bottom: 1px solid #ccc;
height: auto;
padding-top: 8px;
padding-bottom: 8px;
white-space: normal;
}
.autocompletedemoCustomTemplate .autocomplete-custom-template li:last-child {
border-bottom-width: 0;
}
.autocompletedemoCustomTemplate .autocomplete-custom-template .item-title,
.autocompletedemoCustomTemplate .autocomplete-custom-template .item-metadata {
display: block;
line-height: 2;
}
.autocompletedemoCustomTemplate .autocomplete-custom-template .item-title md-icon {
height: 18px;
width: 18px;
}
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body ng-app="MyApp" ng-cloak>
<div ng-controller="DemoCtrl as ctrl" layout="column" ng-cloak="" class="autocompletedemoCustomTemplate" ng-app="MyApp">
<md-content layout-padding="" layout="column">
<form ng-submit="$event.preventDefault()">
<md-autocomplete md-selected-item="ctrl.selectedItem" md-search-text-change="ctrl.searchTextChange(ctrl.searchText)" md-search-text="ctrl.searchText" md-selected-item-change="ctrl.selectedItemChange(item)" md-items="item in ctrl.querySearch(ctrl.searchText)"
md-item-text="item.name" md-min-length="0" placeholder="Pick an Angular repository" md-menu-class="autocomplete-custom-template">
<md-item-template>
<span class="item-title">
<strong>Company name:</strong> {{item.Company_Name}}
</span>
<strong>Client Ids:</strong>
<span ng-repeat="clientId in item.Assets">
<span class="item-metadata">
<span class="item-metastat">
 <ng-md-icon icon="subdirectory_arrow_right" style="fill: gray" size="24"></ng-md-icon>
{{clientId}}
</span>
</span>
</span>
</md-item-template>
</md-autocomplete>
</form>
</md-content>
</div>
<!--CSS files-->
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.0-rc4/angular-material.min.css">
<link rel="stylesheet" href="https://material.angularjs.org/1.1.0-rc4/docs.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic">
<link rel="stylesheet" href="/css/style.css">
<!-- Angular Material requires Angular.js Libraries -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-animate.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-route.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-messages.min.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-114/svg-assets-cache.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.0-rc4/angular-material.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-material-icons/0.7.0/angular-material-icons.min.js"></script>
<!-- Your application bootstrap -->
<script type="text/javascript" src="js/autocomplete.js"></script>
</body>
</html>
这是 server.js
文件和 mockData.json 文件。
"use strict";
//Lets define a port we want to listen to
const PORT = 8080;
//Init Vars
var express = require('express');
var fs = require('fs');
var app = express();
//Init Functions
//we allow CORS: http://enable-cors.org/server_expressjs.html
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.listen(PORT, function() {
console.log('Example app listening on port ' + PORT + '!');
});
//GET methods
app.get('/getClients', function(req, res, next) {
let assetsQuery = function(array, word) {
let result = false;
array.forEach(function(element, index, array) {
if (element.toLowerCase().trim().includes(word))
result = true;
});
return result;
};
//get parameters from GET: https://scotch.io/tutorials/use-expressjs-to-get-url-and-post-parameters
var query = req.param('word');
let dbQuery = JSON.parse(fs.readFileSync('mockData.json', 'utf8'));
let result = [];
if (query == null || query == "" || typeof query == 'undefined')
result = dbQuery.mockupData;
else {
query = query.toLowerCase().trim();
dbQuery.mockupData.forEach(function(element, index, array) {
if (element.Company_Name.toLowerCase().trim().includes(query) || assetsQuery(element.Assets, query))
result.push(element);
});
}
res.send(result);
});
假数据文件:
{
"mockupData": [{
"AccountID": "cweu4xy733z06mqv96",
"Company_Name": "Wal - Mart Stores, Inc",
"Assets": ["gme-wal1", "gme-wal2"]
}, {
"AccountID": "3tvjnjzud1jz2xy6ug",
"Company_Name": "Volkswagen Automotive",
"Assets": ["gme-vol1", "gme-aut2"]
}, {
"AccountID": "ht019dupmtb4jinzpo",
"Company_Name": "Vitol Commodities",
"Assets": ["gme-vit1", "gme-com2"]
}, {
"AccountID": "l2fd73rbpc48d1hvua",
"Company_Name": "Verizon Telecommunications",
"Assets": ["gme-ver1", "gme-tel2"]
}, {
"AccountID": "2iygtyj2do2pi8e4dv",
"Company_Name": "Valero",
"Assets": ["gme-vale1", "gme-valoil2"]
}, {
"AccountID": "1ojav89f9qka85vpwb",
"Company_Name": "United Health Health care",
"Assets": ["gme-usahc1", "gme-uhhc2"]
}, {
"AccountID": "y9ikfaj2qgf18d0vsw",
"Company_Name": "Trafigura Commodities",
"Assets": ["gme-traf1", "gme-trafcom2"]
}, {
"AccountID": "nxhpt5unxsjedui5sk",
"Company_Name": "Toyota Automotive",
"Assets": ["gme-toy1", "gme-oyota2"]
}, {
"AccountID": "hqu18f8wy43oc5kfde",
"Company_Name": "Total",
"Assets": ["gme-total1", "gme-tot2"]
}, {
"AccountID": "tsc9aures3yjpy2nrr",
"Company_Name": "Tata Group Conglomerate",
"Assets": ["gme-tata1", "gme-grcon2"]
}, {
"AccountID": "paoxb086omzi1uu5zr",
"Company_Name": "State Grid Electric utility",
"Assets": ["gme-sgeu1", "gme-elecs2"]
}, {
"AccountID": "7u2fhcatofgqjzv2tf",
"Company_Name": "Sinopec Group",
"Assets": ["gme-sin1", "gme-sinoil2"]
}, {
"AccountID": "hbg285h3nk206zmdqb",
"Company_Name": "Saudi Aramco",
"Assets": ["gme-sau1", "gme-aram2"]
}, {
"AccountID": "xyg1n25grvl74f69l6",
"Company_Name": "Samsung Conglomerate",
"Assets": ["gme-sam1", "gme-sacomg2"]
}, {
"AccountID": "aaoexfcqln8peec4dv",
"Company_Name": "Royal Dutch Shell",
"Assets": ["gme-royal1", "gme-forthequeen"]
}, {
"AccountID": "rubvrmy2ucrvh3elrj",
"Company_Name": "Phillips 66",
"Assets": ["gme-phil1", "gme-ips2"]
}, {
"AccountID": "5gmxscwazuokverzbd",
"Company_Name": "Petrobras",
"Assets": ["gme-pedro1", "gme-petro2"]
}, {
"AccountID": "nsx4y558obp62dwn47",
"Company_Name": "PDVSA",
"Assets": ["gme-pdvsa1", "gme-pgas"]
}, {
"AccountID": "80o7d5p4wrx1ueygmx",
"Company_Name": "Microsoft Conglomerate",
"Assets": ["gme-microsoft1", "gme-evil2"]
}, {
"AccountID": "1v14j9i5w8sy4iipuv",
"Company_Name": "McKesson Pharmaceuticals",
"Assets": ["gme-mckesson1", "gme-mckeuticals2"]
}, {
"AccountID": "92ac8fl1dk1nh5v408",
"Company_Name": "Lukoil",
"Assets": ["gme-luko1", "gme-loil2"]
}, {
"AccountID": "pn3w8dxqrzytlmanhe",
"Company_Name": "Kuwait Petroleum Corporation",
"Assets": ["gme-kuwait1", "gme-war2"]
}, {
"AccountID": "35mtlyc6bnbxhuav1d",
"Company_Name": "Koch Industries Conglomerate",
"Assets": ["gme-koch1", "gme-kindus2"]
}, {
"AccountID": "n4gu863njqnndvmk3d",
"Company_Name": "Japan Post Conglomerate",
"Assets": ["gme-jap1", "gme-konichiwa2"]
}, {
"AccountID": "gkrllbxd56r9gi4q7t",
"Company_Name": "Industrial and Commercial Bank of China Financial services",
"Assets": ["gme-china1", "gme-LongLiveTsungLee2"]
}, {
"AccountID": "qgb1gudy460seqgzo3",
"Company_Name": "Honda Automotive",
"Assets": ["gme-honhon1", "gme-autohon2"]
}]
}
问题
如何使结果的下拉框更大?
最佳答案
您可以使用未记录的参数 md-dropdown-items
:
<md-autocomplete
md-selected-item="selectedItem"
md-search-text="searchText"
md-items="item in getMatches(searchText)"
md-item-text="item.display"
md-dropdown-items="10">
<span md-highlight-text="searchText">{{item.display}}</span>
</md-autocomplete>
默认值为 5(从版本 angular-material#ad0581ddd3 开始)。
您可能还想根据窗口的高度调整此值:
<md-autocomplete
md-selected-item="selectedItem"
md-search-text="searchText"
md-items="item in getMatches(searchText)"
md-item-text="item.display"
md-dropdown-items="nbItems">
<span md-highlight-text="searchText">{{item.display}}</span>
</md-autocomplete>
然后在您的 Controller 中设置nbItems
。例如:
$scope.nbItems = 5 + $mdMedia('(min-height: 400px)') * 5 + $mdMedia('(min-height: 600px)') * 10;
因此,如果高度低于 400px,您将有 5 个元素,如果低于 600px,则有 10 个元素,而高于 600px 则有 20 个元素。
希望对你有帮助
注意:md-dropdown-items
参数对于md-select
不存在,仅对于md-autocomplete
存在。
太糟糕了;)
关于javascript - 设置自定义高度 Angular Material 自动完成下拉列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37661507/