0

I have what would seem to be a simple problem with AngularJS - apologies if so. I'm new and have searched all over and can't quite find an answer to what I want to do.

Basically I have a $http request that is getting a list of 'Cards' from a server which I'm then using ng-repeat to build in the HTML. I then want to populate those Cards with a number of 'Metrics' - also retrieved from the server. I have a controller for the 'Cards' (parents) and a separate controller for the 'Metrics' (children).

My issue is that I can't work out how to reference the ID of the parent 'Card' when making the child $http request.

Below is the HTML & JS that I am using - any help would be appriciated:


HTML:

<div class="Dashboard container-fluid" ng-controller="DahsboardCardController as Dashboard">

    <div ng-repeat="Card in Dashboard.DashboardCards">

        <div class="DashboardCard card">
            {{Card.CardDisplayName}}

            <div class="DashboardCardBody" ng-controller="DahsboardMetricController as Metric">
                <div ng-repeat="Metric in Metric.DashboardMetrics">
                    {{Metric.MetricDisplayName}}
                </div>
            </div>

        </div>

    </div>

JS:

(function () {
    var app = angular.module('OtterDashboard', [ ]);

    app.controller('DahsboardCardController', [ '$http', function($http) {

        //Declare a varaible for the data
        var DashboardCards = this;

        //Set the varaiable to an empty array to receive the data
        DashboardCards.DashboardCards = [ ];

        $http({
            //Request the data
            method: 'GET',
            dataType: 'jsonp',
            url: '/api.svc/tbl_Card',
            useDefaultXhrHeader: false,
            headers: {'Content-type': 'application/json'},
            headers: {'Accept': 'application/json;odata=light;q=1,application/json;odata=verbose;q=0.5'},
            crossDomain: true,
        }).then(function successCallback(data) {
            //The data was sucessfully received, populate the variable with it
            DashboardCards.DashboardCards = data.data.d.results;
        }, function errorCallback(response) {
            //There was an error
            console.log('Card data could not be retrieved');
        });

    }]);

    app.controller('DahsboardMetricController',  ['$http', function($http, Card) {

        //Declare a varaible for the data
        var DashboardMetrics = this;

        //Set the varaiable to an empty array to receive the data
        DashboardMetrics.DashboardMetrics = [ ];

        $http({
            //Request the data
            method: 'GET',
            dataType: 'jsonp',
            url: '/api.svc/DashboardMetric?Card=%27' + **???reference to parent card ID???** + '%27',
            useDefaultXhrHeader: false,
                headers: {'Content-type': 'application/json'},
                headers: {'Accept': 'application/json;odata=light;q=1,application/json;odata=verbose;q=0.5'},
                crossDomain: true,
        }).then(function successCallback(data) {
            //The data was sucessfully received, populate the variable with it
            DashboardMetrics.DashboardMetrics = data.data.d.results;
        }, function errorCallback(response) {
            //There was an error
            console.log('Metric data could not be retrieved');
        });

    }]);

})();

Thank you!

Chetan Sharma
  • 334
  • 2
  • 11
Jay Tyler
  • 1
  • 6
  • Can you simplify this for us? Remove all the code that does not mattter – Bas Slagter Oct 12 '15 at 12:53
  • Thanks for the prompt reply Ben. I've cut down the HTML, sorry. I think everything in the JS is required. – Jay Tyler Oct 12 '15 at 12:58
  • dont know your card structure what I am guessing Card.id or Card.CardID? Can you actually post your Dashboard json – Jax Oct 12 '15 at 12:59
  • It's card.CardID - thank you – Jay Tyler Oct 12 '15 at 12:59
  • what is the reason for nested controller? A directive is probably more appropriate and keep in mind that `ng-repeat` creates a child scope – charlietfl Oct 12 '15 at 13:00
  • So I have the parent items which then contain multiple children. I want to load all the parents and then populate each parent with its children. Each parent may have any number of children (which will be different for each parent). – Jay Tyler Oct 12 '15 at 13:03
  • Thanks charlietfl - so I should change both of the controllers to directives? Apologies but I'm still new and not 100% sure on the differences and the tutorials I've seen all look to use controllers. I can investigate how to change to a directive though. – Jay Tyler Oct 12 '15 at 13:05

1 Answers1

0

EDIT 1

Use a service for shared variable between controllers. Look the example:

   app.controller('DahsboardCardController', ['$http', function($http, $sharedResource) {
        var DashboardCards = this;
        DashboardCards.DashboardCards = [ ];

        $http({
            method: 'GET',
            dataType: 'jsonp',
            url: '/api.svc/tbl_Card',
            useDefaultXhrHeader: false,
            headers: {'Content-type': 'application/json'},
            headers: {'Accept': 'application/json;odata=light;q=1,application/json;odata=verbose;q=0.5'},
            crossDomain: true,
        }).then(function successCallback(data) {
            DashboardCards.DashboardCards = data.data.d.results;
            $sharedResource.set("id", "<pass id value>");

        }, function errorCallback(response) {
            console.log('Card data could not be retrieved');
        });
    }]);

 app.controller('DahsboardMetricController',  ['$http', function($http, Card, $sharedResource) {
        var DashboardMetrics = this;

        DashboardMetrics.DashboardMetrics = [];

        $http({
            method: 'GET',
            dataType: 'jsonp',
            url: '/api.svc/DashboardMetric?Card=%27' + $sharedResource.get("id") + '%27',
            useDefaultXhrHeader: false,
            headers: {'Content-type': 'application/json'},
            headers: {'Accept': 'application/json;odata=light;q=1,application/json;odata=verbose;q=0.5'},
            crossDomain: true,
        }).then(function successCallback(data) {
            DashboardMetrics.DashboardMetrics = data.data.d.results;
        }, function errorCallback(response) {
            console.log('Metric data could not be retrieved');
        });
    }]);

    app.factory('$sharedResource', function () {
        var property = {};

        return {
            get: function (key) {
                return property[key];
            },
            set: function(key, value) {
                property[key] = value;
            }
        };
    });

EDIT 2

When working with angularjs is recomended use a one object for print object in table. Why this is a beautiful s2.

Look this example. To help you in development. Use the sample function pass the parentId in load(CardId). This function will run in the page load.

I too fix code html. You used the alias controller before input field of same.

var app = angular.module("App", []);

app.controller('DahsboardCardController', ['$scope', function($scope) {
        $scope.DashboardCards = [{
            CardId: "111",
            CardDisplayName: "Card 1"
        }, {
            CardId: "222",
            CardDisplayName: "Card 2"
        }, {
            CardId: "333",
            CardDisplayName: "Card 3"
        }];
    }
]);

app.controller('DahsboardMetricController', ['$scope', function($scope) {
        $scope.load = function(CardIdParent) {
            console.log(CardIdParent);
        };
    }
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="App" class="Dashboard container-fluid" ng-controller="DahsboardCardController as Dashboard">
    {{Dashboard.DashboardCards}}
    <div ng-repeat="Card in DashboardCards">
        <div class="DashboardCard card">
            {{Card.CardDisplayName}}
            <div class="DashboardCardBody" ng-controller="DahsboardMetricController as Metric"  ng-init="load(Card.CardId)">
                This a id parent: {{Card.CardId}}
                <div ng-repeat="MetricItem in DashboardMetrics">
                    {{MetricItem.MetricDisplayName}}
                </div>
            </div>
        </div>
    </div>
</div>
Emir Marques
  • 2,603
  • 2
  • 16
  • 22
  • Thank you. I'm getting two errors when I try that: TypeError: Cannot read property 'set' of undefined TypeError: Cannot read property 'get' of undefined – Jay Tyler Oct 12 '15 at 13:11
  • Edit my example. Try now! – Emir Marques Oct 12 '15 at 13:29
  • Getting closer - error now "Unknown provider: CardProvider <- Card <- DahsboardMetricController". Thanks again. – Jay Tyler Oct 12 '15 at 13:37
  • Also, I'm not sure what I need to put where you've put "" - I assume some reference to the current Card ID but unsure how to reference that - apologies if I am being dumb! – Jay Tyler Oct 12 '15 at 13:42
  • In id value pass reference the ID of the parent 'Card' . Look example now – Emir Marques Oct 12 '15 at 13:50
  • So in the format - data.data.d.CardID ? Any idea why I'm getting the Unknown provider: CardProvider <- Card <- DahsboardMetricController" error? – Jay Tyler Oct 12 '15 at 14:05
  • I have removed 'Card' from the DahsboardMetricController and this has resolved that error (sorry, I thought you added this but I must have done previously when I was trying to fix the problem). --I still don't know what I need to put into "" to reference the current ID though? – Jay Tyler Oct 12 '15 at 14:48
  • you pass id shared between controllers – Emir Marques Oct 12 '15 at 14:54
  • I'm sorry but I'm just not getting it. I do not know how to pass the ID. In the section you have put "". I do not know what to put here. I have tried "data.data.d.CardID", I have tried to reference the Controller, I have tried to reference the alias of the Controller. None of this works. Can you be more specific about what goes in the space "" please? – Jay Tyler Oct 12 '15 at 14:55
  • Pass as $sharedResource.set("id", data.any.id). Look your object parent for this – Emir Marques Oct 12 '15 at 16:14
  • Put json of Dashboard.DashboardCards in your question – Emir Marques Oct 12 '15 at 18:06
  • I really appreciate your help but it still does not work. To get the results I use "data.data.d.results" - the id of the objects is called "CardID" - whichever permutation I use it simply either does not work or says that the object is undefined. Surely I have to specify which of the parent objects I want to set the ID from? Currently there are 6 parent items, how would it know which one to set it as? I have no idea why this is so hard - I thought this was the whole reason to use Angular. I'm completely lost and have no idea what the functions you've suggested are doing. – Jay Tyler Oct 14 '15 at 12:25