Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them; it only takes a minute:

I'm a rank newbie to Angular, and I'm attempting to port an old jQuery-based app to NG. The JSON I'm starting with (parsed from an XML file) looks like this:

{
    "setUps":{
        "cartImage":
        {
            "_cartIm":"addtocart.gif",
            "_cartIm_o":"addtocart.gif"
        }
        ,"_supportImsPath":"/"
    },
    "product":
    {
        "matrix":
        {
            "thumbnails":[
                {
                    "_myLabel":"Antique Brass Distressed",
                    "_thumbImage":"3",
                    "_cartCode":"160"
                },
                {
                    "_myLabel":"Antique Brass Light",
                    "_thumbImage":"156",
                    "_cartCode":"156"
                },
                {
                    "_myLabel":"Old Iron",
                    "_thumbImage":"ap",
                    "_cartCode":"157"
                },
                {
                    "_myLabel":"Oil-Rubbed Bronze",
                    "_thumbImage":"ob",
                    "_cartCode":"3"
                }
            ],
            "_myLabel":"Finishes"
        },
        "_Title":"Flower Cabinet Knob",
        "_itNum":"100407x"
    }
}

What I need to do with this is output specific elements on my template - first and foremost, the matrix object with its associated thumbnails. In this example, there is only one matrix, but for many of the products there are multiples, each with their own thumbnail arrays.

This is the controller:

var XMLt = angular.module("XMLtest",[]);
XMLt.factory("Xfactory",function($http){
    var factory = [];
    factory.getXML = function(){
        return $http.get(productXML);
    }
    return factory;
});

XMLt.controller("Xcontroller",function($scope,Xfactory) {
    $scope.Xcontroller = [];
    loadXML();
    function loadXML() {
        Xfactory.getXML().success(function (data) {
            var x2js = new X2JS();
            prodData = x2js.xml_str2json(data);
            $scope.thisItem = prodData.contents;
            $scope.matrices = [];
            angular.forEach($scope.thisItem.matrix,function(value,key)
            {
                $scope.matrices.push(value,key);
            });
        });
    }
});

And this is my view template:

<div ng-controller="Xcontroller">
    <h2>Title: {{ thisItem.product._Title }}</h2>
    <div ng-repeat="thisMatrix in thisItem.product" class="matrix">
        {{ thisMatrix._myLabel }}
    </div>
</div>

My problem is that this ng-repeat, not surprisingly, returns a div for every child element of the product that it finds, not just the matrix. So I wind up with a couple of empty divs (for _Title and _itNum) in addition to the matrix div.

I've seen quite a few examples of filtering by comparing value literals, but they don't seem to apply in this case. I also tried writing a custom filter:

$scope.isObjType = function(input) {
    return angular.isObject(input);
};

<div ng-repeat="thisMatrix in thisItem.product | filter:isObjType(matrix)">

That seemed to have no effect, still returning the extraneous divs. I can't seem to wrap my head around how I'd limit the repeat to a specific object type. Am I thinking of this the completely wrong way? If so, I'd welcome any input.

share|improve this question
    
note: prodData = x2... missing var – Kevin B Oct 20 '14 at 15:42
    
I don't see a reason for the outer ngrepeat, it is what is causing your extra divs. – Kevin B Oct 20 '14 at 15:44
    
My apologies. The outer div is the matrix output, with the inner for outputting the thumbnails of the individual matrices. I should have left the inner out of this example. I've edited my post. – bwomack Oct 20 '14 at 16:09
    
here's the issue though. thisMatrix will contain an array of thumbnails on the first iteration, and the string "Finishes" on the second. i doubt that's what you wanted. In other words, you're either iterating over the wrong thing, or don't need to iterate in the first place. – Kevin B Oct 20 '14 at 16:18
1  
please rewrite your question without mentioning your business cases. It seems the answer to your question is very simple, but the question itself is not. – allenhwkim Oct 20 '14 at 16:33

1 Answer 1

up vote 0 down vote accepted

Since you only have one matrix, you don't need the repeat for the matrix label. You only need it for the thumbnails.

<div ng-controller="Xcontroller">
    <h2>Title: {{ thisItem.product._Title }}</h2>
    <div class="matrix">
        {{ thisItem.product.matrix._myLabel }}
        <div ng-repeat="thisThumbnail in thisItem.product.matrix.thumbnails" class="thumbnail">           
            {{thisThumbnail._myLabel}}
        </div>
    </div>
</div>

If it were possible to have multiple matrixes, the object would need to be modified to be able to represent that (by wrapping the matrix object in an array.)

Update per comments:

If you have the possiblity of multiple matrixes, you will need to modify the object to ensure that it is consistent when there is 1 vs when there are 2+.

<div ng-controller="Xcontroller">
    <h2>Title: {{ thisItem.product._Title }}</h2>
    <div ng-repeat="thisMatrix in thisItem.product.matrix" class="matrix">
        {{ thisMatrix._myLabel }}
        <div ng-repeat="thisThumbnail in thisMatrix.thumbnails" class="thumbnail">           
            {{thisThumbnail._myLabel}}
        </div>
    </div>
</div>

and in controller:

XMLt.controller("Xcontroller",function($scope,Xfactory) {
    $scope.Xcontroller = [];
    loadXML();
    function loadXML() {
        Xfactory.getXML().success(function (data) {
            var x2js = new X2JS();
            prodData = x2js.xml_str2json(data);
            // must always have an array of matrixes
            if (!prodData.contents.product.matrix.slice) {
                prodData.contents.product.matrix = [prodData.contents.product.matrix];
            }
            $scope.thisItem = prodData.contents;
            $scope.matrices = [];
            angular.forEach($scope.thisItem.matrix,function(value,key)
            {
                $scope.matrices.push(value,key);
            });
        });
    }
});
share|improve this answer
    
Thanks, but there are many cases in which there will be multiple matrices, wrapped as arrays as you've noted. – bwomack Oct 20 '14 at 18:07
    
then you need the object to reflect that, even when there is only one. – Kevin B Oct 20 '14 at 18:14
    
Thanks! That's very helpful, and just what I was looking for. – bwomack Oct 20 '14 at 19:42

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.