4

this is the html code:

<li ng-repeat="data in spreadGroupData" ng-click="channelList(data.campaigns,data.name)"><a href="javascript:void(0)">{{data.name}}</a></li>`

this is the code i write in the services.js:

services.getChannelName = function($scope,channelidList){
        httpurl = "api/account/"+nowuID+"/channel/channellist?id=" + channelidList;
        $http.get(httpurl).success(function(data){
            if(data.length>0){
                $scope.spreadGroupData = [];
                for(var i in data){
                    var group = {};
                    group.campaigns = data[i].id;
                    group.name = data[i].name;
                    $scope.spreadGroupData.push(group);
                }
            }
        });
    };

there are data in $scope.spreadGroupData,why couldn't show in the view page?

Now I know I shouldn't use $scope in the service,but the param 'channelidList' I get it from another service method. How to rewrite this all?

services.getListData = function(scope,flag){
         var reportList = "quality_report",merger = true;
         if(typeof flag!='undefined' && flag == 1){
             reportList = "fakequality_report";
             merger = false;
         }
        var cids = scope.spreadUrls,dateArr=scope.date.split(" - "),startDate = "",endDate = "",channelids = "";
        if(dateArr.length==1){
            startDate = endDate = dateArr[0];
        }else{
            startDate = dateArr[0];
            endDate = dateArr[1];
        }
        if(cids!=null){
            if(cids!='All'){
                channelids = "&channelid="+cids.join(",");
            }
            if(scope.selecteds != -1 &&  typeof(scope.selecteds) != "undefined"){
                httpurl = "api/app/"+scope.selecteds+"/report/"+reportList+"?startdate="+startDate+"&enddate="+endDate+channelids;
                $http.get(httpurl).success(function(data,status){
                    scope.tabTitle = data.name;
                     var tableList = services.colToRow(data.val),cidlen = cids.length;
                     scope.tabTotal = services.dataToTotal(data.val,cidlen);
                     var key = data.key,tabname = [],zero = [],tabListInfo = [],allnames = scope.spreadNames;
                     for(var i=0;i<scope.tabTotal.length;i++){
                        zero[i] = 0;
                     }
                     for(i=0;i<cidlen;i++){
                        var idx = $.inArray(allnames[i],key);
                        tabListInfo[i] = new Array();
                        if(idx>-1){
                            tabListInfo[i] = tableList[idx];
                        }else{
                            tabListInfo[i] = zero;
                        }

                        if(merger){
                            var temp = [];
                            for(var j=0;j<tabListInfo[i].length;j++){
                                temp[j] = tabListInfo[i][j];
                            }
                            temp.unshift(scope.spreadNames[i]);
                            tabListInfo[i] = temp;
                        }
                     }
                     var channelIdList = [];
                     if(key.length>0){
                         var n = 0;
                         for(var i in scope.spreadData){
                             for(var j in key){
                                 if(key[j] == scope.spreadData[i].name){
                                     n++;
                                     channelIdList.push(scope.spreadData[i].channel);
                                     if(n>20) break;
                                 }
                             }
                         }
                     }
                     services.getChannelName(scope,channelIdList.join(","));
                     scope.tabname = scope.spreadNames;
                     if(merger){
                         var tabListObj = [];
                         if(reportList == "quality_report"){
                             for(var i = 0; i <tabListInfo.length; i++){
                                 tabListObj.push({
                                     "name" : tabListInfo[i][0],
                                     "hitNum" : tabListInfo[i][1],
                                     "reSchedulNum" : tabListInfo[i][2],
                                     "activeDevice" : tabListInfo[i][3],
                                     "activeRate" : tabListInfo[i][4],
                                     "payment" : tabListInfo[i][5],
                                     "spdID" : cids[i]
                                 });
                             }
                         }
                         scope.tabListInfo = tabListObj;
                     }else{
                         if(reportList == "fakequality_report"){
                             var tabListObj = [];
                             for(var i = 0; i <tabListInfo.length; i++){
                                 tabListObj.push({
                                     "name" : scope.tabname[i],
                                     "reSchedulNum" : tabListInfo[i][0],
                                     "hitNum" : tabListInfo[i][1],
                                     "errHitNum" : tabListInfo[i][2],
                                     "errHitRate" : tabListInfo[i][3],
                                     "activeDevice" : tabListInfo[i][4],
                                     "errActDevice" : tabListInfo[i][5],
                                     "errActRate" : tabListInfo[i][6],
                                     "spdID" : cids[i]
                                 });
                             }
                             scope.tabListInfo = tabListObj;
                         }else{
                             scope.tabListInfo = tabListInfo;
                         }
                     }
                     scope.spreadIDs = cids;
                }).error(function(data){
                    services.loginTimeout(data);
                });
                }
            }
    };
Parker Song
  • 151
  • 10
  • 1
    You are overwrite group in each iteration. You must put var group = {} out of loop. – robBerto Mar 30 '15 at 07:30
  • I need to push a new object to the array, so i need to overwrite group. There are there objects in $scope.spreadGroupData,I have consoled it. – Parker Song Mar 30 '15 at 07:39

3 Answers3

2

You should never pass $scope object to service, service should always have a reusable method which will exposed. I'd suggest you service method should return promise to the controller caller method, and caller method will implement the binding logic inside controller promise success method.

Service Method

services.getChannelName = function(channelidList) {
    httpurl = "api/account/" + nowuID + "/channel/channellist?id=" + channelidList;
    return $http.get(httpurl).success(function(data) {
        return data;
    }).error(function(err) {
        return err;
    });
};

Controller Method

$scope.getChannelName = function() {
    $scope.spreadGroupData = [];
    service.getChannelName(channelidList).then(function(data) {
        if (data.length > 0) {
            for (var i in data) {
                var group = {};
                group.campaigns = data[i].id;
                group.name = data[i].name;
                $scope.spreadGroupData.push(group);
            }
        }
    }, function(err) {
        console.log("Error" + err);
    })
}

Update

Whole idea about the code like below. Need to maintain proper code stack resolve. First service method will return promise, on resolved of it you need to do change in some scope variables, then you will call second service method which has promise, on resolved of it you need to update scope.

Code

services.getListData(flag).then(function(data) { //you may need to pass multiple parameter to this
    //then do scope operation
    service.getChannelName(channelidList).then(function(res) {
        if (res.length > 0) {
            for (var i in data) {
                var group = {};
                group.campaigns = data[i].id;
                group.name = data[i].name;
                $scope.spreadGroupData.push(group);
            }
        }
    }, function(err) {
        console.log("Error" + err);
    });
})
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • @ParkerSong This would the best way to do cod in angular way , Do upvote if you can.. Thanks :) – Pankaj Parkar Mar 30 '15 at 07:57
  • I just joined a new company and beginning to learn ng. The code was wrriten by the other colleague, in the service.js she almost use the scope in every method. As you suggested, I need to rewrite the whole service.:-( – Parker Song Mar 30 '15 at 08:06
  • 1
    @ParkerSong Yes $scope should be depend on service and service should never update `$scope` directly, it considered as code smell in angular..I'd personally prefer to rewrite a code..As per angular code should separate as it use mvc pattern – Pankaj Parkar Mar 30 '15 at 09:03
  • The param is from another service method. What should I do to rewrite this service? – Parker Song Mar 30 '15 at 09:27
  • @ParkerSong that is what you are trying to say..it'll mess you are making you service tightly coupled with particular controller.. – Pankaj Parkar Mar 30 '15 at 09:34
  • **Pull one hair and the whole body is affected** this is a really hard work – Parker Song Mar 30 '15 at 09:46
  • @ParkerSong Its my pleasure, sorry to force you to do rework, but I'm sure, after this re factoring you will be having good understanding about angular – Pankaj Parkar Mar 30 '15 at 10:36
  • For more understanding of service do refer this http://stackoverflow.com/questions/15666048/service-vs-provider-vs-factory/28262966#28262966 – Pankaj Parkar Mar 30 '15 at 10:44
1

I only saw one little thing that might be cause a problem, there is a missing var keyword in front of the httpurl variable and I only add that to below demo.

The view you need to show your data:

<body ng-controller="myController">
    Spread Group Data
    <br />
    ------------------------------------------------------------
    <li ng-repeat="data in spreadGroupData"
        ng-click="channelList(data.campaigns,data.name)">
        <a href="javascript:void(0)">{{data.name}}</a>
    </li>
</body>

I used a mock json provide to simulate your service and call it in a controller directly:

// Prepared a mock json array on the http://beta.json-generator.com and below url returns:
// [{"name":"Item 1","id":1},{"name":"Item 2","id":2},{"name":"Item 3","id":3},{"name":"Item 4","id":4}]
var httpurl = "http://beta.json-generator.com/api/json/get/LoUmNC4";

$http.get(httpurl).success(function(data) {
  if (data.length > 0) {
    $scope.spreadGroupData = [];
    for (var i in data) {
      var group = {};
      group.campaigns = data[i].id;
      group.name = data[i].name;
      $scope.spreadGroupData.push(group);
    }
  }
});

If your service is independent from your controller, then you can pass $scope to your service method. But in this demo I implemented the http call block directly in a main controller. Besides this as @pankajparkar's said do not use the $scope in factories or service unrelated services and take and use response data from that like services. Please check promise and $q in order to handle asynchronous calls.

This is a working demo: Demo

okanozeren
  • 555
  • 4
  • 10
  • Thanks, I have another promblem,please see the question I just updated. – Parker Song Mar 30 '15 at 09:25
  • There is question about that: http://stackoverflow.com/questions/15509457/passing-current-scope-to-an-angularjs-service. Passing $scope to a service is not a best-practice but you can use if you have to do and you do not have any choice. If you ask me "if it works leave it alone". – okanozeren Mar 30 '15 at 09:59
0

Place $scope.spreadGroupData = []; outside $http call :-

services.getChannelName = function($scope,channelidList){
        httpurl = "api/account/"+nowuID+"/channel/channellist?id=" + channelidList;
        $scope.spreadGroupData = [];
        $http.get(httpurl).success(function(data){
            if(data.length>0){
                for(var i in data){
                    var group = {};
                    group.campaigns = data[i].id;
                    group.name = data[i].name;
                    $scope.spreadGroupData.push(group);
                }
            }
        });
    };
squiroid
  • 13,809
  • 6
  • 47
  • 67
  • 1
    why you are encouraging people to use scope inside service method – Pankaj Parkar Mar 30 '15 at 07:39
  • 1
    @pankajparkar you are right i was just giving the OP answer and forgot :-P to elaborate about best practice not to use $scope inside the service . :-) Thanks :) – squiroid Mar 30 '15 at 08:29