1

I have an array of numbers, e.g:

var data=['1','4','2','1','6','9','1','5',]

and I want to convert it into two-dimensional array, like this one below:

result = [['1','4','2','1'],['6','9','1','5']]

my goal is to make dynamic grid style menu system in ionic from the example below

<div class="text-center" ng-init="models = [['12','1','2','3','3'],['4','4','5','6','7']]">
    <div ng-repeat="m in models">
        <span class="control-label1" ng-repeat="movie in m track by $index">
    {{movie}}</span>
    </div>
</div>

in order to do this i needed to add all my value in 2 dimensional array. i am adding value in the given function below

 //this function make populate my array with unique value
  $scope.addhourinArray = function (value) {

        if (value) {
            if ($scope.hourArray.indexOf(value) == -1) {
                $scope.hourArray.push(value);
            }
        }
    };


   for (var i = 0; i < data.length; i++) {
        $scope.addhourinArray(hour);
    }
nur farazi
  • 1,197
  • 12
  • 32

1 Answers1

1

It's not exactly clear what you mean in this context as the "Angular Way" - especially as the creation of a 2 dimensional array from a 1 dimensional one doesn't seem to be an Angular problem.

Furthermore it isn't clear why and in which way the data feeding the menu is dynamic (especially as your example simply grabs it from an ng-init) - so for the following I'm going to assume that the data originates from an asynchronous source.

  • Typically asynchronous sources are wrapped inside an Angular service. Any logic necessary for the transformation of that data would typically be part of the service, not the controller - unless the transformation is highly specific to that controller and the service is serving other parts of the application with an alternate data representation.
  • You should probably consider "componentizing" your menu with a directive which holds its own template and controller.
  • Only use $scope only when you absolutely have to. The "Controller As" syntax was introduced back in Angular JS 1.1.5 and support has been steadily improving since then.

The following tries to demonstrate some of these ideas:

<!DOCTYPE html>
<html>
<head>
  <title>angular 1.x directive for movie-menu custom element</title>
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
</head>
<body> 
  <div ng-app="myApp">
    <!-- register 'movie-menu.html' with $templateCache -->
    <script type="text/ng-template" id="movie-menu.html">
      <div ng-repeat="m in mmvm.models">
        <span ng-repeat="movie in m track by $index">
          {{movie}}
        </span>
      </div>
    </script>

    <!-- movie-menu custom element -->
    <movie-menu></movie-menu> 
  </div>  
  <script type="text/javascript">
    (function () {

      // using $q (instead of $http) to fake async call returning promise
      dataServiceFactory.$inject = ['$q']; 
      function dataServiceFactory ($q) {

        function transformData (items) {
          var rowLength = ((items.length % 2) == 0 ? items.length : items.length - 1)/2,
          top = items.slice(0, rowLength), 
          bottom = items.slice(rowLength, rowLength + rowLength); 

          return [top, bottom];
        }

        function fakeData() {      
          var data, transformed, resultP, resolveResult, rejectResult;

          // FAKING IT- static data
          data = ['12','1','2','3','3','4','4','5','6','7','x'];

          // transform data
          transformed = transformData(data);

          // FAKING IT- wrap result in a promise
          // This service would chain a promise off 
          // of the promise from the async call
          resultP = $q(function(resolve, reject) {
            resolveResult = resolve;
            rejectResult = reject;        
          });

          // FAKING IT - resolve promise immediately
          resolveResult(transformed);

          return resultP; // promise to deliver cleaved data 
        }

        return { 
          getData: fakeData 
        }; // return the dataService instance

      } // end dataServiceFactory 

      MovieMenuCtrl.$inject = ['dataService'];
      function MovieMenuCtrl (dataService) {
        var vm;

        function setModels (result) {
          vm.models = result;
        }

        vm = this;
        dataService.getData().then(setModels);    
      }

      // A directive definition object (Ddo) factory
      movieMenuDdoFactory.$inject = [];
      function movieMenuDdoFactory () {
        // return the directive definition object
        return {
          restrict: 'E',
          scope: {}, // isolate scope for the controllerAs reference to exist in without danger of collision 
          replace: true,
          templateUrl: 'movie-menu.html',
          controller: 'MovieMenuCtrl',
          controllerAs: 'mmvm',
          bindToController: true
        };
      }

      angular
        .module('myApp', [])
        .factory('dataService', dataServiceFactory)
        .controller('MovieMenuCtrl', MovieMenuCtrl)
        .directive('movieMenu', movieMenuDdoFactory);

    })();
  </script>     
</body>
</html>

Some inspiration coming from:
Chapter 1: Building a simple element directive - JSFiddle
How I've Improved My Angular Apps by Banning ng-controller
Refactoring Angular Apps to Component Style
AngularJS: Developer Guide: Dependency Injection - $inject Property Annotation
AngularJS: API: $q - $q constructor
Array.prototype.slice() - JavaScript | MDN

Peer Reynders
  • 546
  • 3
  • 6