我正在使用ng-repeat和我的代码我有'n'个基于ng-repeat的文本框。我想将文本框与三列对齐。
这是我的代码
<div class="control-group" ng-repeat="oneExt in configAddr.ext">
{{$index+1}}.
<input type="text" name="macAdr{{$index+1}}"
id="macAddress" ng-model="oneExt.newValue" value=""/>
</div>
答案 0 :(得分:251)
最可靠且技术上最正确的方法是转换控制器中的数据。这是一个简单的块功能和用法。
function chunk(arr, size) {
var newArr = [];
for (var i=0; i<arr.length; i+=size) {
newArr.push(arr.slice(i, i+size));
}
return newArr;
}
$scope.chunkedData = chunk(myData, 3);
然后你的观点会是这样的:
<div class="row" ng-repeat="rows in chunkedData">
<div class="span4" ng-repeat="item in rows">{{item}}</div>
</div>
如果ng-repeat
中有任何输入,您可能希望在数据被修改或提交时取消组合/重新加入阵列。以下是$watch
中的内容,以便始终以原始合并格式提供数据:
$scope.$watch('chunkedData', function(val) {
$scope.data = [].concat.apply([], val);
}, true); // deep watch
许多人更喜欢在带有过滤器的视图中完成此操作。这是可能的,但只应用于显示目的!如果您在此过滤视图中添加输入,则会导致可以解决但不漂亮或不可靠的问题。
此过滤器的问题是每次都返回新的嵌套数组。 Angular正在观察过滤器的返回值。过滤器第一次运行时,Angular知道该值,然后再次运行它以确保它完成更改。如果两个值相同,则循环结束。如果没有,过滤器将一次又一次地触发,直到它们相同,或者Angular意识到正在发生无限消化循环并关闭。因为Angular之前没有跟踪新的嵌套数组/对象,所以它总是看到返回值与前一个不同。要修复这些“不稳定”过滤器,必须将过滤器包装在memoize
函数中。 lodash
具有memoize
函数,最新版本的lodash还包含chunk
函数,因此我们可以使用npm
模块非常简单地创建此过滤器,并使用{编译脚本{1}}或browserify
。
请记住:仅显示!如果您正在使用输入,请在控制器中进行过滤!
安装lodash:
webpack
创建过滤器:
npm install lodash-node
以下是此过滤器的示例:
var chunk = require('lodash-node/modern/array/chunk');
var memoize = require('lodash-node/modern/function/memoize');
angular.module('myModule', [])
.filter('chunk', function() {
return memoize(chunk);
});
<div ng-repeat="row in ['a','b','c','d','e','f'] | chunk:3">
<div class="column" ng-repeat="item in row">
{{($parent.$index*row.length)+$index+1}}. {{item}}
</div>
</div>
关于垂直列(从上到下列出)而不是水平(从左到右),确切的实现取决于所需的语义。分布不均匀的列表可以以不同的方式分布。这是一种方式:
1 4
2 5
3 6
<div ng-repeat="row in columns">
<div class="column" ng-repeat="item in row">
{{item}}
</div>
</div>
然而,获取列的最直接,最简单的方法是使用CSS columns:
var data = ['a','b','c','d','e','f','g'];
$scope.columns = columnize(data, 3);
function columnize(input, cols) {
var arr = [];
for(i = 0; i < input.length; i++) {
var colIdx = i % cols;
arr[colIdx] = arr[colIdx] || [];
arr[colIdx].push(input[i]);
}
return arr;
}
.columns {
columns: 3;
}
答案 1 :(得分:62)
这个解决方案非常简单:
<强> JSON:强>
[{id:"1",name:"testA"},{id:"2",name:"test B"},{id:"3",name:"test C"},{id:"4",name:"test D"},{id:"5",name:"test E"}]
<强> HTML:强>
<div ng-controller="MyCtrl">
<table>
<tr ng-repeat="item in items" ng-switch on="$index % 3">
<td ng-switch-when="0">
{{items[$index].id}} {{items[$index].name}}
</td>
<td ng-switch-when="0">
<span ng-show="items[$index+1]">
{{items[$index+1].id}} {{items[$index+1].name}}
</span>
</td>
<td ng-switch-when="0">
<span ng-show="items[$index+2]">
{{items[$index+2].id}} {{items[$index+2].name}}
</span>
</td>
</tr>
</table>
</div>
答案 2 :(得分:19)
不需要数据操作的干净,适应性强的解决方案:
HTML:
<div class="control-group" class="label"
ng-repeat="oneExt in configAddr.ext"
ng-class="{'new-row': startNewRow($index, columnBreak) }">
{{$index+1}}.
<input type="text" name="macAdr{{$index+1}}"
id="macAddress{{$index}}" ng-model="oneExt.newValue" />
</div>
CSS:
.label {
float: left;
text-align: left;
}
.new-row {
clear: left;
}
JavaScript:
$scope.columnBreak = 3; //Max number of colunms
$scope.startNewRow = function (index, count) {
return ((index) % count) === 0;
};
这是一种简单的解决方案,可以动态地将数据呈现为行和列,而无需操作您尝试显示的数据数组。另外,如果您尝试调整浏览器窗口的大小,您可以看到网格动态地适应屏幕/ div的大小。
(我还为你的id添加了{{$ index}}后缀,因为如果不这样做,ng-repeat会尝试创建具有相同id的多个元素。)
答案 3 :(得分:15)
div
来表示可能是表的数据。
因此结合m59的过滤器(上面的回答),这里是如何在表格中显示它。
<table>
<tr class="" ng-repeat="rows in foos | chunk:2">
<td ng-repeat="item in rows">{{item}}</td>
</tr>
</table>
答案 4 :(得分:7)
以下是一种更简单的方法:
<table>
<tr ng-repeat="item in lists" ng-hide="$index%2!==0">
<td>
<label>{{ lists[$index].name}}</label>
</td>
<td ng-hide="!lists[$index+1]">
<label>{{ lists[$index+1].name}}</label>
</td>
</tr>
</table>
Cumulo Nimbus的答案对我很有用,但我希望这个网格由div包裹,当列表太长时可以显示滚动条。
为实现这一目标,我将style="height:200px; overflow:auto"
添加到表格周围的div中,使其显示为单个列。
现在适用于数组长度为一个。
答案 5 :(得分:4)
我有一个功能并将其存储在一个服务中,所以我可以在我的应用程序中使用它:
<强>服务强>
app.service('SplitArrayService', function () {
return {
SplitArray: function (array, columns) {
if (array.length <= columns) {
return [array];
};
var rowsNum = Math.ceil(array.length / columns);
var rowsArray = new Array(rowsNum);
for (var i = 0; i < rowsNum; i++) {
var columnsArray = new Array(columns);
for (j = 0; j < columns; j++) {
var index = i * columns + j;
if (index < array.length) {
columnsArray[j] = array[index];
} else {
break;
}
}
rowsArray[i] = columnsArray;
}
return rowsArray;
}
}
});
<强>控制器:强>
$scope.rows = SplitArrayService.SplitArray($scope.images, 3); //im splitting an array of images into 3 columns
<强>标记:强>
<div class="col-sm-12" ng-repeat="row in imageRows">
<div class="col-sm-4" ng-repeat="image in row">
<img class="img-responsive" ng-src="{{image.src}}">
</div>
</div>
答案 6 :(得分:2)
一个简单的技巧&#34; clearfix&#34; Bootstrap推荐的CSS:
fComboBoxDefault.valueProperty().addListener(new ChangeListener() {
@SuppressWarnings("rawtypes")
@Override
public void changed(ObservableValue ov, Object arg1,
Object arg2) {
// Do Something ...
}
}
});
&#13;
许多优点:高效,快速,使用Boostrap建议,避免可能的$ digest问题,而不是改变Angular模型。
答案 7 :(得分:2)
我的做法是各种各样的事情。
我的目标是让网格适应屏幕尺寸。我希望lg
有3列,sm
和md
有2列,xs
有1列。
首先,我使用角度$window
服务创建了以下范围函数:
$scope.findColNumberPerRow = function() {
var nCols;
var width = $window.innerWidth;
if (width < 768) {
// xs
nCols = 1;
}
else if(width >= 768 && width < 1200) {
// sm and md
nCols = 2
} else if (width >= 1200) {
// lg
nCols = 3;
}
return nCols;
};
然后,我使用了@Cumulo Nimbus提出的课程:
.new-row {
clear: left;
}
在包含ng-repeat
的div中,我添加了resizable
指令,如this page中所述,以便每次调整窗口大小时,更新角度$window
服务用新的价值观。
最终,在重复的div中我有:
ng-repeat="user in users" ng-class="{'new-row': ($index % findColNumberPerRow() === 0) }"
请让我知道这种方法的任何缺陷。
希望它有所帮助。
答案 8 :(得分:1)
此示例生成嵌套转发器,其中外部数据包含一个内部数组,我想在两列中列出。这个概念适用于三列或更多列。
在内栏中,我重复&#34;行&#34;直到达到极限。通过将项目数组的长度除以所需的列数(在这种情况下为2)来确定限制。除法方法位于控制器上,并作为参数传递当前数组长度。然后,JavaScript切片(0,array.length / columnCount)函数将限制应用于转发器。
然后调用第二列转发器并重复slice(array.length / columnCount,array.length),它在第二列中生成数组的后半部分。
<div class="row" ng-repeat="GroupAccess in UsersController.SelectedUser.Access" ng-class="{even: $even, odd: $odd}">
<div class="col-md-12 col-xs-12" style=" padding-left:15px;">
<label style="margin-bottom:2px;"><input type="checkbox" ng-model="GroupAccess.isset" />{{GroupAccess.groupname}}</label>
</div>
<div class="row" style=" padding-left:15px;">
<div class="col-md-1 col-xs-0"></div>
<div class="col-md-3 col-xs-2">
<div style="line-height:11px; margin-left:2px; margin-bottom:2px;" ng-repeat="Feature in GroupAccess.features.slice(0, state.DivideBy2(GroupAccess.features.length))">
<span class="GrpFeature">{{Feature.featurename}}</span>
</div>
</div>
<div class="col-md-3 col-xs-2">
<div style="line-height:11px; margin-left:2px; margin-bottom:2px;" ng-repeat="Feature in GroupAccess.features.slice( state.DivideBy2(GroupAccess.features.length), GroupAccess.features.length )">
<span class="GrpFeature">{{Feature.featurename}}</span>
</div>
</div>
<div class="col-md-5 col-xs-8">
</div>
</div>
</div>
// called to format two columns
state.DivideBy2 = function(nValue) {
return Math.ceil(nValue /2);
};
希望这有助于以另一种方式查看解决方案。 (PS这是我在这里发表的第一篇文章!: - ))
答案 9 :(得分:1)
所有这些答案看起来都是过度设计的。
到目前为止,最简单的方法是在col-md-4列引导程序中设置输入div,然后由于引导程序的12列特性,引导程序会自动将其格式化为3列:
<div class="col-md-12">
<div class="control-group" ng-repeat="oneExt in configAddr.ext">
<div class="col-md-4">
<input type="text" name="macAdr{{$index}}"
id="macAddress" ng-model="oneExt.newValue" value="" />
</div>
</div>
</div>
答案 10 :(得分:1)
这是一种简单易行的方式。它更加手动,最终会出现凌乱的标记。我不建议这样做,但有些情况可能会有用。
这是一个小提琴链接http://jsfiddle.net/m0nk3y/9wcbpydq/
HTML:
<div ng-controller="myController">
<div class="row">
<div class="col-sm-4">
<div class="well">
<div ng-repeat="person in people = data | limitTo:Math.ceil(data.length/3)">
{{ person.name }}
</div>
</div>
</div>
<div class="col-sm-4">
<div class="well">
<div ng-repeat="person in people = data | limitTo:Math.ceil(data.length/3):Math.ceil(data.length/3)">
{{ person.name }}
</div>
</div>
</div>
<div class="col-sm-4">
<div class="well">
<div ng-repeat="person in people = data | limitTo:Math.ceil(data.length/3):Math.ceil(data.length/3)*2">
{{ person.name }}
</div>
</div>
</div>
</div>
</div>
JS:
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
$scope.Math = Math;
$scope.data = [
{"name":"Person A"},
...
];
});
此设置要求我们在标记上使用一些数学:/,因此您需要通过添加以下行来注入数学:$scope.Math = Math;
答案 11 :(得分:1)
<div class="row">
<div class="col-md-4" ng-repeat="remainder in [0,1,2]">
<ul>
<li ng-repeat="item in items" ng-if="$index % 3 == remainder">{{item}}</li>
</ul>
</div>
</div>
答案 12 :(得分:1)
我没有.row
<div class="col col-33 left" ng-repeat="photo in photos">
Content here...
</div>
和css
.left {
float: left;
}
答案 13 :(得分:0)
Lodash现在内置了一个chunk方法,我个人使用它:https://lodash.com/docs#chunk
基于此,控制器代码可能如下所示:
$scope.groupedUsers = _.chunk( $scope.users, 3 )
查看代码:
<div class="row" ng-repeat="rows in groupedUsers">
<div class="span4" ng-repeat="item in rows">{{item}}</div>
</div>
答案 14 :(得分:0)
另一种方法是将width:33.33%; float:left
设置为这样的包装器div:
<div ng-repeat="right in rights" style="width: 33.33%;float: left;">
<span style="width:60px;display:inline-block;text-align:right">{{$index}}</span>
<input type="number" style="width:50px;display:inline-block" ">
</div>
答案 15 :(得分:0)
我是bootstrap和angularjs中的新手,但这也可能使每4个项目的数组成为一个组,结果几乎就像3列。 这个技巧使用bootstrap break line原则。
<div class="row">
<div class="col-sm-4" data-ng-repeat="item in items">
<div class="some-special-class">
{{item.XX}}
</div>
</div>
</div>
答案 16 :(得分:0)
我发现自己处于类似的情况,想要生成每列3列的显示组。但是,虽然我使用的是bootstrap,但我试图将这些组分成不同的父div。我也想做一些通用的东西。
我用2 ng-repeat
接近它,如下所示:
<div ng-repeat="items in quotes" ng-if="!($index % 3)">
<div ng-repeat="quote in quotes" ng-if="$index <= $parent.$index + 2 && $index >= $parent.$index">
... some content ...
</div>
</div>
这样可以很容易地更改为不同数量的列,并分成几个父div。
答案 17 :(得分:0)
基于m59的非常好的答案。我发现模型输入如果改变就会模糊,所以你一次只能改变一个字符。对于需要它的任何人来说,这是一个新的对象列表:
编辑已更新,可在一个页面上处理多个过滤器
app.filter('partition', function() {
var cache = {}; // holds old arrays for difference repeat scopes
var filter = function(newArr, size, scope) {
var i,
oldLength = 0,
newLength = 0,
arr = [],
id = scope.$id,
currentArr = cache[id];
if (!newArr) return;
if (currentArr) {
for (i = 0; i < currentArr.length; i++) {
oldLength += currentArr[i].length;
}
}
if (newArr.length == oldLength) {
return currentArr; // so we keep the old object and prevent rebuild (it blurs inputs)
} else {
for (i = 0; i < newArr.length; i += size) {
arr.push(newArr.slice(i, i + size));
}
cache[id] = arr;
return arr;
}
};
return filter;
});
这就是用法:
<div ng-repeat="row in items | partition:3:this">
<span class="span4">
{{ $index }}
</span>
</div>
答案 18 :(得分:0)
此代码将有助于在lg和md模式下将元素与三列对齐,在sm模式下将元素对齐为两列,而在xs模式下将单个列对齐
<div class="row">
<div ng-repeat="oneExt in configAddr.ext">
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-4">
{$index+1}}.
<input type="text" name="macAdr{{$index+1}}"
id="macAddress" ng-model="oneExt.newValue" value=""/>
</div>
</div>
答案 19 :(得分:0)
以防万一有人想要Angular 7(及更高版本),这是我在一个应用程序中使用的示例:
HTML:
<div class="container-fluid">
<div class="row" *ngFor="let reports of chunkData; index as i">
<div *ngFor="let report of reports" class="col-4 col-sm-4"
style="border-style:solid;background-color: antiquewhite">{{report}}</div>
</div>
</div>
.TS文件
export class ConfirmationPageComponent implements OnInit {
chunkData = [];
reportsArray = ["item 1", "item 2", "item 3", "item 4", "item 5", "item 6"];
constructor() {}
ngOnInit() {
this.chunkData = this.chunk(this.reportsArray, 3);
}
chunk(arr, size) {
var newArr = [];
for (var i = 0; i < arr.length; i += size) {
newArr.push(arr.slice(i, i + size));
}
return newArr;
}
}
这是一个很棒的解决方案,用于根据您从数据库中迭代的项目数来动态创建新的列/行。谢谢!
答案 20 :(得分:-1)
这回答了原始问题,即如何在一列中获得1,2,3。 - 由kuppu 2月8日和14日在13:47提出要求
angularjs代码:
function GetStaffForFloor(floor) {
var promiseGet = Directory_Service.getAllStaff(floor);
promiseGet.then(function (pl) {
$scope.staffList = chunk(pl.data, 3); //pl.data; //
},
function (errorOD) {
$log.error('Errored while getting staff list.', errorOD);
});
}
function chunk(array, columns) {
var numberOfRows = Math.ceil(array.length / columns);
//puts 1, 2, 3 into column
var newRow = []; //array is row-based.
for (var i = 0; i < array.length; i++) {
var columnData = new Array(columns);
if (i == numberOfRows) break;
for (j = 0; j < columns; j++)
{
columnData[j] = array[i + numberOfRows * j];
}
newRow.push(columnData);
}
return newRow;
////this works but 1, 2, 3 is in row
//var newRow = [];
//for (var i = 0; i < array.length; i += columns) {
// newRow.push(array.slice(i, i + columns)); //push effectively does the pivot. array is row-based.
//}
//return newRow;
};
查看代码(注意:使用bootstrap 3):
<div class="staffContainer">
<div class="row" ng-repeat="staff in staffList">
<div class="col-md-4" ng-repeat="item in staff">{{item.FullName.length > 0 ? item.FullName + ": Rm " + item.RoomNumber : ""}}</div>
</div>
</div>