javascript - 设置自定义高度 Angular Material 自动完成下拉列表

标签 javascript css angularjs autocomplete angular-material

背景

我正在使用 Angular Material 进行自定义自动完成,我想将自动完成下拉结果框的高度设置为更大的值。

研究

为了实现这一点,我做了一个研究并得出结论,Angular Material 不支持这个,并且这个问题只会在 Angular Material 2(为 AngularJS2 发布)中解决:

阅读后,我意识到有些人找到了绕过这种强制 CSS 限制的方法 (Angular Material Design Layout custom sizes),但无论我如何尝试,我都看不到他们的任何建议都能奏效。

代码

我的示例应用程序由一个 index.html、一个 autocomplete.js 文件和一个带有 mockData 的 server.js 文件组成.json 文件。

以下是index.htmlautocomplete.jsstyle.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">
                                    &emsp;<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/

相关文章:

javascript - jQuery select2 为所选项目添加类

javascript - 有没有办法禁用对 div 及其子节点的关注?

css - 使用文档模式在 IE9 中运行良好的网站 IE7 在使用 IE7 标准作为文档模式的 IE11 中出现问题

CSS word-wrap 导致 div 后空格溢出

angularjs - 如何在 jasmine 中测试被拒绝的 Angular (1.6.1) promise ?

forms - angular - 在指令中的表单元素之间动态更改验证要求

javascript - 是否需要包含 Typescript 的 java lint 提示,VS - 2013

javascript - 下面的 .forEach 语句有什么作用?

javascript - Nodejs 到 MSSQL 十进制数字问题

javascript - 饼图不呈现 React Chart.js