Reputation: 1422
I have a table with three different levels of data, when I call the child level of data using an ng-click the data is diplayed ok but when I call the grandson level the data is not displayed, the response of my WS is ok because I can see it loged in my console so I after some time I realized that I need to nest my ng-repeat's in order to display the data from the grandson level but I don get how to do it, I checked also the ng-repeat-start directive but dont know if it apply to my htlm structure, this is what I have on my view.
<table class="table table-bordered drilldown-table" id="fixTable" style="height: 505px">
<tbody ng-repeat="cat in (exportData.result.slice(0, exportData.result.length-2))" >
<tr class="parent">
<td ng-click="drillDownSubcategoriesCat(cat.merchMetrics.DEPT_NBR,cat.merchMetrics.CATG_GRP_NBR,cat.merchMetrics.DEPT_CATG_NBR)" drill-down>+</td>
<td style="text-align: left">{{cat.merchMetrics.DEPT_CATG_DESC}}</td>
<!--SALES-->
<td>{{cat.merchMetrics.SALES_AMOUNT_LW | number : 2}}</td>
<td>{{cat.merchMetrics.SALES_LW_CHG_LY}}%</td>
<td>{{cat.merchMetrics.SALES_L4W_CHG_LY}}%</td>
<td>{{cat.merchMetrics.SALES_L13W_CHG_LY}}%</td>
<td>{{cat.merchMetrics.SALES_L52W_CHG_LY}}%</td>
<td>{{cat.merchMetrics.SALES_LW_VS_L13W}}</td>
</tr>
<tr ng-repeat="subcat in drillDownSubcatCatList['D' + cat.merchMetrics.DEPT_NBR + 'CG' + cat.merchMetrics.CATG_GRP_NBR + 'C' + cat.merchMetrics.DEPT_CATG_NBR]" class="child" ng-if="!$last" style="background-color: #f3eee9">
<td ng-click="drillDownCategoryItemsCat(subcat.merchMetrics.DEPT_NBR, subcat.merchMetrics.CATG_GRP_NBR, subcat.merchMetrics.DEPT_CATG_NBR, subcat.merchMetrics.DEPT_SUBCATG_NBR)" drill-down>+</td>
<td style="text-align: left; padding-left: 25px">{{subcat.merchMetrics.DEPT_SUBCATG_DESC}}</td>
<!--SALES-->
<td>{{subcat.merchMetrics.SALES_AMOUNT_LW | number : 2}}</td>
<td>{{subcat.merchMetrics.SALES_LW_CHG_LY}}%</td>
<td>{{subcat.merchMetrics.SALES_L4W_CHG_LY}}%</td>
<td>{{subcat.merchMetrics.SALES_L13W_CHG_LY}}%</td>
<td>{{subcat.merchMetrics.SALES_L52W_CHG_LY}}%</td>
<td>{{subcat.merchMetrics.SALES_LW_VS_L13W}}</td>
</tr>
<tr ng-repeat="items in drillDownCategoryItemCatList[nbrSubcatItem]" class="grandson" ng-if="!$last" style="background-color: #f3eee9">
<td></td>
<td style="text-align: left; padding-left: 45px">{{items.merchMetrics.DEPT_SUBCATG_DESC}}}</td>
<!--SALES-->
<td>{{items.merchMetrics.SALES_AMOUNT_LW | number : 2}}</td>
<td>{{items.merchMetrics.SALES_LW_CHG_LY}}%</td>
<td>{{items.merchMetrics.SALES_L4W_CHG_LY}}%</td>
<td>{{items.merchMetrics.SALES_L13W_CHG_LY}}%</td>
<td>{{items.merchMetrics.SALES_L52W_CHG_LY}}%</td>
<td>{{items.merchMetrics.SALES_LW_VS_L13W}}</td>
</tr>
</tbody>
To generate the data from the child and grandson level I call to functions.
$scope.drillDownSubcatCatList = {};
$scope.subcatNbr = '';
$scope.drillDownSubcategoriesCat = function (dept,group,catg) {
$scope.nbr1 = [dept];
$scope.nbr2 = [group];
$scope.nbr3 = [catg];
$scope.nbrSubcat = 'D' + $scope.nbr1 + 'CG' + $scope.nbr2 + 'C' + $scope.nbr3;
$scope.nbrSubcat.toString();
$scope.subCategoryConst = ['Product Sales (Subcategory Rank)'];
$scope.drillDownRecords = "5";
console.log($scope.nbr1);
console.log($scope.nbr2);
console.log($scope.nbr3);
console.log("NBR: " + $scope.nbrSubcat);
if (!($scope.nbrSubcat in $scope.drillDownSubcatCatList)) {
$scope.loadViewCategories = false;
$scope.graphLoading = "loading";
searchFactory.search('merchandise',
{
timeStamp: $scope.dateTime,
timeFrameType: $scope.whenType,
custMembSelectionType: $scope.customerType,
locationSelectionType: $scope.locationType,
merchandiseSelectionType: "Category",
startYear: $scope.whenStartParentYear,
endYear: $scope.whenStartParentYear,
startUnit: $scope.whenStartValue,
endUnit: $scope.whenStartValue,
comparator: $scope.locationType.indexOf('(Comp)', $scope.locationType.length - '(Comp)'.length) !== -1,
locationSelections: $scope.locationSelected,
merchandiseSelections: [$scope.nbrSubcat],
custMembSelections: $scope.customerSelected,
metricSelections: $scope.subCategoryConst,
rankOrder: $scope.drillDownRecords
}).success(function (data) {
console.log("drillDownSubcategories OK");
$scope.loadViewCategories = true;
$scope.graphLoading = "white";
$scope.canvasContent = true;
$scope.exportDataCategoryDrillDown = data;
$scope.metricSelected = $scope.filters.baropt.displayName;
if (data.error) {
$scope.noData = "There are no results based on your selected dropdowns. Please change your selection.";
$scope.data = undefined;
$scope.hasError = true;
}
$scope.isExportDisabled = 'auto';
if (!$scope.drillDownSubcatCatList[$scope.nbrSubcat]) {
$scope.drillDownSubcatCatList[$scope.nbrSubcat] = $scope.exportDataCategoryDrillDown.result;
}
}).error(function (ret, status) {
console.log(ret, status);
if (status == 500 || status == 0) {
if (ret.error.indexOf("Filter criteria not found!") > -1 || ret.error.indexOf("Bad Selections!") > -1) {
$scope.errorMessage = "The combination of dropdowns you selected is invalid. Please select a different combination.";
} else {
$scope.errorMessage = "The database may be down. Please contact Data Cafe Development Team - Applications for help.";
}
} else if (status == 400) {
$scope.errorMessage = "There was a bad request sent to the database. Please contact Data Cafe Development Team - Applications for help.";
} else {
$scope.errorMessage = "There was an error while trying to process your request. Please contact Data Cafe Development Team - Applications for help.";
}
$scope.hasError = true;
$scope.graphLoading = "white";
$scope.canvasContent = true;
$scope.showCaptions = false;
}
);
}
if($scope.nbrSubcat in $scope.drillDownSubcatCatList) {
console.log("--------------- " + $scope.nbrSubcat);
console.log("RETURN DD SUBCATEGORY LIST: ", $scope.drillDownSubcatCatList);
}
}
And this is the second function:
$scope.drillDownCategoryItemCatList = {};
$scope.drillDownCategoryItemsCat = function (dept,group,catg,subcat) {
$scope.nbr1 = [dept];
$scope.nbr2 = [group];
$scope.nbr3 = [catg];
$scope.nbr4 = [subcat];
$scope.nbrSubcatItem = 'D' + $scope.nbr1 + 'CG' + $scope.nbr2 + 'C' + $scope.nbr3 + 'SC' + $scope.nbr4;
$scope.nbrSubcatItem.toString();
$scope.ItemsConst = ['Product Sales (Item Rank)'];
$scope.drillDownRecords = "5";
console.log($scope.nbr1);
console.log($scope.nbr2);
console.log($scope.nbr3);
console.log($scope.nbr4);
console.log("NBR: " + $scope.nbrSubcatItem);
if (!($scope.nbrSubcatItem in $scope.drillDownCategoryItemCatList)) {
$scope.loadViewCategories = false;
$scope.graphLoading = "loading";
searchFactory.search('merchandise',
{
timeStamp: $scope.dateTime,
timeFrameType: $scope.whenType,
custMembSelectionType: $scope.customerType,
locationSelectionType: $scope.locationType,
merchandiseSelectionType: "SubCategory",
startYear: $scope.whenStartParentYear,
endYear: $scope.whenStartParentYear,
startUnit: $scope.whenStartValue,
endUnit: $scope.whenStartValue,
comparator: $scope.locationType.indexOf('(Comp)', $scope.locationType.length - '(Comp)'.length) !== -1,
locationSelections: $scope.locationSelected,
merchandiseSelections: [$scope.nbrSubcatItem],
custMembSelections: $scope.customerSelected,
metricSelections: $scope.ItemsConst,
rankOrder: $scope.drillDownRecords
}).success(function (data) {
console.log("drillDownCategortyItems OK");
$scope.loadViewCategories = true;
$scope.graphLoading = "white";
$scope.canvasContent = true;
$scope.exportDataCategoryItemDrillDown = data;
$scope.metricSelected = $scope.filters.baropt.displayName;
if (data.error) {
$scope.noData = "There are no results based on your selected dropdowns. Please change your selection.";
$scope.data = undefined;
$scope.hasError = true;
}
$scope.isExportDisabled = 'auto';
if (!$scope.drillDownCategoryItemCatList[$scope.nbrSubcatItem]) {
$scope.drillDownCategoryItemCatList[$scope.nbrSubcatItem] = $scope.exportDataCategoryItemDrillDown.result;
}
}).error(function (ret, status) {
console.log(ret, status);
if (status == 500 || status == 0) {
if (ret.error.indexOf("Filter criteria not found!") > -1 || ret.error.indexOf("Bad Selections!") > -1) {
$scope.errorMessage = "The combination of dropdowns you selected is invalid. Please select a different combination.";
} else {
$scope.errorMessage = "The database may be down. Please contact Data Cafe Development Team - Applications for help.";
}
} else if (status == 400) {
$scope.errorMessage = "There was a bad request sent to the database. Please contact Data Cafe Development Team - Applications for help.";
} else {
$scope.errorMessage = "There was an error while trying to process your request. Please contact Data Cafe Development Team - Applications for help.";
}
$scope.hasError = true;
$scope.graphLoading = "white";
$scope.canvasContent = true;
$scope.showCaptions = false;
}
);
}
if($scope.nbrSubcatItem in $scope.drillDownCategoryItemCatList) {
console.log("LIST FROM CATEGORY TO ITEM LEVEL: ", $scope.drillDownCategoryItemCatList);
}
}
As I mentioned before, the parent and the child level are displayed ok, so any idea on how can I nest the ng-repeat's in order to allow my grandson level to be displayed?
Upvotes: 0
Views: 124
Reputation: 28737
There is something strange here that you require a single table in the UI, but the underlying model is of a triply nested object. ng-repeat is not meant to be nested at sibling DOM levels.
The way I would recommend implementing this is to use an angular filter that will wrap all of your data into a single array that you can call ng-repeat on.
Your controller has wayyyyy too much logic in it. And I think this is contributing to the difficulties. In general, the controller should be in charge of displaying data that is being provided by angular services. The angular services should provide the data in a way that is easy for the controllers to consume.
If you find yourself creating nested if statements, xhr requests, and error handling inside of the controller, then you are doing something wrong. All of this should be refactored to several services (each service should have a SINGLE responsibility). Then you should have one of the services provide data to the controller that is easy for it to consume.
This is a bit of a vague answer, and not really a simple one. I think that the problems you are having come from not fully understanding how Angular implements the MVC pattern.
Upvotes: 1