-->

Ng-repeat trying to create a counter index

2019-03-06 12:31发布

问题:

I have a table that I auto-increment each row with based on the user's selection.

The problem I am faced with is ng-repeat copies the column I cannot differentiate between them. For example, each cell in the column is numbered the same using index. I would like to have a way of identifying where the user clicks on the cell.

<table class="table table-bordered">
        <thead>
         <tr>
           <th></th>
           <th style="table-layout:fixed; text-align: center;" scope="col" colspan="2">Sales</th>
           <th style="table-layout:fixed; text-align: center;" scope="col" colspan="2">Service</th>
           <th style="table-layout:fixed; text-align: center;" scope="col" colspan="2">Accounting</th>
           <th style="vertical-align:top; text-align: center;" scope="col" colspan="2">Parts</th>
           <th style="vertical-align:top; text-align: center;" scope="col" colspan="2">Body Shop</th>
           <th style="vertical-align:top; text-align: center;" scope="col" colspan="2">Other</th>
         </tr>
         <tr>
           <th></th>
           <th class="start-end-time" style="text-align: center; font-size: .9em; color: #999;">Start</th>
           <th class="start-end-time" style="text-align: center; font-size: .9em; color: #999;">End</th>
           <th class="start-end-time" style="text-align: center; font-size: .9em; color: #999;">Start</th>
           <th class="start-end-time" style="text-align: center; font-size: .9em; color: #999;">End</th>
           <th class="start-end-time" style="text-align: center; font-size: .9em; color: #999;">Start</th>
           <th class="start-end-time" style="text-align: center; font-size: .9em; color: #999;">End</th>
           <th class="start-end-time" style="text-align: center; font-size: .9em; color: #999;">Start</th>
           <th class="start-end-time" style="text-align: center; font-size: .9em; color: #999;">End</th>
           <th class="start-end-time" style="text-align: center; font-size: .9em; color: #999;">Start</th>
           <th class="start-end-time" style="text-align: center; font-size: .9em; color: #999;">End</th>
           <th class="start-end-time" style="text-align: center; font-size: .9em; color: #999;">Start</th>
           <th class="start-end-time" style="text-align: center; font-size: .9em; color: #999;">End</th>
         </tr>
         </thead>
           <tr ng-repeat="time in times">
               <td>{{weekdays[$index]}}</td>
               <td class="start-end-time" updated-row ng-repeat-start="(key,dept) in time" data-index="{{[key]}} start" editable-field time="dept.start"></td>
               <td class="start-end-time" updated-row="{{$index}}" data-index="{{[key]}}" ng-repeat-end editable-field  time="dept.end"></td>

               <!-- {{times[$index][key].start}} -->
               Monday Service start time {{times[0] |date: "shortTime"}}
               <!-- <div id="HoursTable" newtable></div> -->

My controller

pp.controller('main', ['$scope', '$location', function($scope, $location) {

    $scope.times = [];
    $scope.timeArr = [];
    $scope.timeObj = {};
    $scope.clickedIndex;

    $scope.departments = ["sales", "service", 'accounting', 'parts', 'bodyShop', 'other'];
    $scope.weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];

    $.each($scope.weekdays, function(index, value) {
        var dayTimes = {};
        $.each($scope.departments, function(index, value) {
            dayTimes[value] = {
                start: '',
                end: ''
            };
        });
        $scope.times.push(dayTimes);
    });
}]);

I have tried to create a data attribute called data-index="{{$index+=1}}"

Hopefully, my example makes a bit of sense. In a nutshell, I would need to give each cell in a column a identifier. As it is now, they all have the same value which stops me from applying any conditional logic.

                  <-- Updated -->
  Located in the hours table page
  ng-init="number = countInit()" 

  controller I added this piece of code as well:

 $scope.countInit = function() {

   return $scope.totalCount++;

}

When I try to display the results in my table using this syntax data-index={{number}}

My results are empty. How can this be? I almost feel like Angular is playing a practical joke on me. Or it could be my ignorance. I prefer to believe the former.

I thought my solution would work. Wondering where I have gone wrong. Can any humble soul help me?

回答1:

Have you tried Angular-datatables? Your html markup for the table looks a bit broken. Angular-datatables took me a while to understand and to wire up but definitely worth the effort, you simply build your JSON data the way you want it and load it into Angular-datatables, the table structure is then generated for you.

Want pagination? or export to PDF/Excel? or you want to search the table or sort it? You still have a lot of work to do before you come close to this library. Here is some of my Angular-datatables code I use to inject a table into the DOM:

            // Bind a click handler to each row
            var myCallback = function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
                $('td', nRow).off("click").bind('click', function () {

// Do something with the row being clicked
console.log(aData);
                });
                return nRow;
            };
$scope.dtOptions = DTOptionsBuilder.fromSource(json.data)                       
                    .withBootstrap()
                    .withButtons(dt_conf.dt_btns)
                    .withOption('fnRowCallback', myCallback)
                    .withOption('order', [[3, "desc"]])
                    .withOption('bDeferRender', dt_conf.defer_render)
                    .withOption('iDisplayLength', dt_conf.dt_length)
                    .withOption("dom", dt_conf.dt_dom)
                    .withPaginationType(dt_conf.paging_type)
                    .withOption('lengthMenu', dt_conf.lengthMenu)
                    .withOption('responsive', true)
                    .withOption('stateSave', dt_conf.save_state);

//The Columns should match your JSON structure
                $scope.dtColumns = [
                    DTColumnBuilder.newColumn('id').withTitle('Id'),
                    // DTColumnBuilder.newColumn('file_id').withTitle('File Id').notVisible(),
                    // DTColumnBuilder.newColumn('file_num').withTitle('File Num').notVisible(),
                    DTColumnBuilder.newColumn('date_time').withTitle('Date Time'),
                    DTColumnBuilder.newColumn('payment_type_id').withTitle('Payment Type Id'),
                    DTColumnBuilder.newColumn('description').withTitle('Description'),
                    DTColumnBuilder.newColumn('creditor').withTitle('Creditor'),
                    DTColumnBuilder.newColumn('amount').withTitle('Amount').renderWith(dt_conf.fnRenderMoney),
                    DTColumnBuilder.newColumn('vat_amount').withTitle('Vat Amount').renderWith(dt_conf.fnRenderMoney),
                    DTColumnBuilder.newColumn('bank').withTitle('Bank').notVisible(),
                    DTColumnBuilder.newColumn('branch_name').withTitle('Branch Name').notVisible(),
                    DTColumnBuilder.newColumn('branch_code').withTitle('Branch Code').notVisible()] 


// Inject the table into your DOM at element (el) and compile with your options.

angular.element(el).html("").append($compile('<table id="' + tid + '" datatable="" ' +
                            'dt-options="{{ dtOptions }}" ' +
                            'dt-columns="{{ dtColumns }}" ' +
                            'class="table table-condensed table-hover table-striped" ' +
                            'style="width:100%"></table>')($scope));

And here is my Factory to configure the options for my DataTables (Took me hours to gather all the options, there are many, and to get this exactly the way I like it! (Internet say 'Thank you!')

app.factory('dt_get', function ($filter) {

    return {
        conf : function conf(xtitle, xmsg) {

            var result = [];
            var xtitle = xtitle; // Title for the exported pdf,xls
            var xmsg = xmsg;     // Subtitle for the exported pdf,xls
            result.paging_type = "full_numbers";
            result.lengthMenu = [[ 5, 10, 15, 50, -1 ],[ 5, 10, 15, 50, "All" ]];
            result.defer_render = true;
            result.save_state = true; //Remember table positions and settings
            result.dt_dom = "<'container-fluid'<'row'<'col-sm-3 text-left'f><'col-sm-6 center-block'p><'col-sm-3 text-right'i>>" +
                    //"<'row'<'col-sm-12 dt-bold'i>>" +
                "<'row'<'col-sm-12'<'panel panel-default'tr>>>" +
                "<'row'<'col-sm-2 text-left'l><'col-sm-6 center-block'p><'col-sm-4 text-right'B>>>";
            result.dt_length = 10;
            result.fnRenderYesNo = function (data, type, full) {
                if (data == "1") {
                    return "<b class='text-success'>YES</b>"
                } else {
                    return "<b class='text-danger'>NO</b>"
                }
            };
            result.fnRenderYesNoInvert = function (data, type, full) {
                if (data == "1") {
                    return "<b class='text-danger'>NO</b>"
                } else {
                    return "<b class='text-success'>YES</b>"
                }
            };

            result.fnRenderMoney = function (data, type, full) {
                    if (data < 0) {
                        return "<b class='text-danger'>" + $filter('currency')(data, 'R ', 2) + "</b>";    //could use currency/date or any angular filter
                    } else {
                        return $filter('currency')(data, 'R ', 2);    //could use currency/date or any angular filter
                    }
            };
            result.dt_btns = [
                {
                    extend: 'colvis',
                    text: 'Edit Cols'
                },
                {
                    extend: 'copyHtml5',
                    text: 'Copy',
                    title: xtitle,
                    message: xmsg,
                    exportOptions: {
                        columns: ':visible'
                    }
                },
                {
                    extend: 'print',
                    text: 'Print',
                    title: xtitle,
                    message: xmsg,
                    exportOptions: {
                        columns: ':visible'
                    }
                },
                {
                    extend: 'excelHtml5',
                    text: 'Excel',
                    title: xtitle,
                    message: xmsg,
                    filename: xtitle + ".xlsx",
                    exportOptions: {
                        columns: ':visible'
                    }
                },
                {
                    extend: 'pdfHtml5',
                    text: 'Pdf',
                    title: xtitle,
                    message: xmsg,
                    filename: xtitle + ".pdf",
                    exportOptions: {
                        columns: ':visible'
                    }
                }
            ]
            return result;
        }

    }

});


回答2:

You can simply do like this,

        var index = 1;
        countIndex = function () {
            return index++;
        }

        $scope.dtColumns = [
            DTColumnBuilder.newColumn(countIndex, "Sr No"),
            DTColumnBuilder.newColumn("some_column_name", "ID").notVisible(),
            DTColumnBuilder.newColumn("some_column_name", "Data"),
            DTColumnBuilder.newColumn("some_column_name", "Status").renderWith(function (data, type) {
                return data == null ? 'Clean' : data;
            }),
            DTColumnBuilder.newColumn("update_date", "Update Date").renderWith(function (data, type) {
                return $filter('date')(data.replace('/Date(', '').replace(')/', ''), 'dd-MMM-yyyy HH:mm:ss');
            })
        ];

This is the simplest way to use index with angular datatable.