具有复杂json对象的ui-grid下拉列表编辑器

时间:2015-03-23 20:06:31

标签: angularjs angular-ui-grid

我使用angular-ui-grid制作一个可编辑的网格,并在这里查看了教程:

http://ui-grid.info/docs/#/tutorial/201_editable

与选项是性别男性/女性等简单结构的示例不同,我试图在模型中绑定复杂的JSON对象。我发现的所有示例都绑定到一个简单的String或Integer对象。

以下是关于Plunker的example(此代码首先从教程中获取,然后稍加修改以显示我面临的问题):

它的核心是数据网格的columnDef配置。

{ 
    name: 'product', 
    field: 'product.name',
    enableCellEdit: true, 
    editType: 'dropdown', 
    editDropdownOptionsArray: $scope.products,
    editableCellTemplate: 'ui-grid/dropdownEditor', 
    editDropdownIdLabel: 'name',
    editDropdownValueLabel: 'name'
}

我尝试将字段和editDropdownIdLabel的值更改为各种选项无济于事。如果您查看示例代码中的3个console.log行51-53,您将看到当您更改所选产品时,名称会更改,但ID保持不变。我希望能够在最终保存此网格中所做的更改时将整个产品对象传递给后端。

3 个答案:

答案 0 :(得分:2)

我有一个非常相似的问题,我找到了一个适合我的解决方案: https://github.com/angular-ui/ng-grid/issues/2808 mltroutt在2月20日的评论 - 一个通用过滤器。

基于此,在你的pluncker我用以下方式尝试了: 您的产品列应如下所示:

name: 'product', 
    field: 'product.id',
    cellFilter: "griddropdown:editDropdownOptionsArray:editDropdownIdLabel:editDropdownValueLabel:row.entity.product.name",
    editableCellTemplate: 'ui-grid/dropdownEditor',
    editDropdownIdLabel: 'id',
    editDropdownValueLabel: 'name',
    editDropdownOptionsArray: $scope.products

然后在你的控制器之后,你必须插入一个这样的过滤器:

.filter('griddropdown', function () {
    return function (input, map, idField, valueField, initial) {
        if (typeof map !== "undefined") {
            for (var i = 0; i < map.length; i++) {
                if (map[i][idField] == input) {
                    return map[i][valueField];
                }
            }
        } else if (initial) {
            return initial;
        }
        return input;
    };
})

答案 1 :(得分:2)

这可以通过在product数组和data数组中使用相同的editDropdownOptionsArray个对象来解决,并将整个product结构放入data选择新的时结构。首先,在columnDef将字段更改为product而不是product.name,将editDropdownIdLabel更改为ref(在下一步中说明),然后添加如图所示cellTemplate

field: 'product',
editDropdownIdLabel: 'ref',
cellTemplate: '<div>{{row.entity.product.name}}</div>'

其次,在每个ref内创建一个自引用字段product,以便在进行选择时可以返回而不只是id。另外,请将product中的data替换为对实际product对象的引用。

let prods = {};
angular.forEach($scope.products, (product) => {
  prods[product.id] = product;  // hash for products by id
  product.ref = product;        // self reference
});
angular.forEach(data, (person) => {
  person.product = prods[person.product.id];
});

现在,当选择一个项目时,一切都保持同步。此外,您(可以说)实际上正在使用网格并按预期选择工具,而不是创建过滤器,观察者等等来尝试解决问题。

现在,如果ui-grid有一个选项(可能是默认值),其中将返回选项数组中的对象,而不是要求返回该对象的字段,这将更容易,并且不会创建循环数据结构。可能是editDropdownIdLabel: '''self'null?或者,也许有人知道更好的方法来获得参考。

此处的Plunker:http://plnkr.co/edit/wjtuwgvZYIxWpkenJS7a?p=preview以及基于@bagavathi的性别字段示例的简单版本 - http://plnkr.co/edit/JJduek?p=preview

此解决方案确实假设您的产品数据真的相同且可以共享,但可能是典型的用例。

答案 2 :(得分:1)

试试这个

 $scope.gridOptions = {
            enableSorting: false,
            enableCellEditOnFocus: false,
            data: data,
            columnDefs: [
                {
                   name: 'product', 
                    field: 'productName',
                    enableCellEdit: true, 
                    editType: 'dropdown', 
                    editDropdownOptionsArray: $scope.products,
                    editableCellTemplate: 'ui-grid/dropdownEditor', 
                    editDropdownIdLabel: 'name',
                    editDropdownValueLabel: 'name'
                }
            ],
            onRegisterApi: function (gridApi) {
                //set gridApi on scope
                $scope.gridApi = gridApi;
                gridApi.edit.on.afterCellEdit($scope, function (rowEntity, colDef, newValue, oldValue) {
                    if (colDef.name === 'product') {
                        for (var i = 0; i < $scope.products.length; i++) {
                            var prod = $scope.products[i];

                            if (prod.name === newValue) {
                                rowEntity.product = prod;
                                break;
                            }
                        }
                        calculateBOption(rowEntity);
                    }                        
                });
            }

}