3

in my app using http.post to get a json array that has been formed, on the server, from multiple arrays. Now my problem is that i should split this array into four separate arrays, I'll explain: JSON array example:

[{"Day", "11/17/2016", "time": "09:45"},
{ "Day", "17/11/2016", "time": "16:50"}, (.....)
{ "Day", "18/11/2016", "time": "11:25"},
{ "Day", "18/11/2016", "time": "12:30"}, (.....)
{ "Day", "11/21/2016", "time": "16:10"},
{ "Day", "11/21/2016", "time": "17:25"}]

Now from this array I should create 4 array, the first in which will be stored for several days, for example (17.11.2016, 11.18.2016, 21.11.2016), the second in which all times will be stored " belonging "to the first day for example (09:45, 16:50), the third in which will be stored all" belonging "times to the second day, for example, (11:25, 12:30) and the fourth in which will be stored all times "belonging" to the third day, for example (16:10, 17:25).

So the result will be something like this:

RESULT:

First array: (17.11.2016, 11.18.2016, 21.11.2016)
Second array: (09:45, 16:50)
Third array: (11:25, 12:30)
Fourth array: (16:10, 17:25)

Who can give me a hand or some advice?

Thank you

UPDATE: this is my controller where i retreive the JSON array:

.controller('AppCtrl', function($scope, $http) {
    $scope.data = {};

    $scope.submit = function(){
        var link = 'http://localhost/ShuttleFIX/api.php';
        $scope.var = "prova";
        $http.post(link, {username : $scope.data.username}).then(function (res){
            $scope.response = res.data;
        });
    };
});

And i should have a select with these options: 17.11.2016, 11.18.2016, 21.11.2016

And a select where i should have these options: 09:45, 16:50 if i choice the first day

kukkuz
  • 41,512
  • 6
  • 59
  • 95
Edoardo
  • 599
  • 2
  • 9
  • 26
  • You've given us an example which is good but you haven't given us the logic for how the 4 arrays would be created. – jbrown Nov 17 '16 at 15:53
  • Try to take a look at either one of the following links: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in or http://stackoverflow.com/questions/558981/getting-a-list-of-associative-array-keys – Bas Pauw Nov 17 '16 at 15:55
  • i need 4 arrays because i should have a form with two selects, one for for choosing a day and the second for choosing a time of that day – Edoardo Nov 17 '16 at 15:57
  • It sounds to me that you are trying a way too difficult solution to a rather simple problem. Still kinda vague though, could you update the question with some code? – Bas Pauw Nov 17 '16 at 16:02
  • ok, now i update it – Edoardo Nov 17 '16 at 16:04
  • i've updated it – Edoardo Nov 17 '16 at 16:11

6 Answers6

1

Question: how can I insert this function for my array ($scope.response) in my controller?

To transform the incoming response you should set the transformResponse property of the configuration object passed to the $http request to a function which will transform the incoming data as per your needs. See transforming-requests-and-responses for more information.

I strongly recommend you move your code that gets data from a server to a service instead of writing it in the controller itself, this service will act as a medium to do GET, POST, etc requests to a server and the controller's job is to do data binding, user-interaction & front-end logic. See this for more information and about coding style used in the below code snippet.

here is the Plunker link for the below code snippet.

The Angular code.

angular
  .module('demo', [])
  .controller('DefaultController', DefaultController)
  .factory('dataService', dataService);

DefaultController.$inject = ['dataService'];

function DefaultController(dataService) {
  var vm = this;

  getEvents();

  function getEvents() {
    return dataService.getEvents()
      .then(function (data) {
        vm.data = data;
        return vm.data;
      });
  }
}

dataService.$inject = ['$http'];

function dataService($http) {
  var service = {
    getEvents: getEvents
  };

  return service;

  function getEvents() {
    var config = {
      transformResponse: function (data, headers) {
        if(headers("content-type") === "application/json; charset=utf-8" && angular.isString(data)) {
          var result = {
            events: [],
            schedules: []
          };

          var events = JSON.parse(data);
          var dates = [];
          for (var i = 0; i < events.length; i++) {
            if (dates.indexOf(events[i].day) === -1) {
              var date = events[i].day;
              dates.push(date);
              result.events.push({
                date: date
              });
            }

            result.schedules.push({
              date: events[i].day,
              time: events[i].time
            });
          }

          return result;
        } else {
          return data;
        }
      }
    };

    return $http.get('events.json', config)
      .then(getEventsCompleted)
      .catch(getEventsFailed);

    function getEventsCompleted(response) {
      return response.data;
    }

    function getEventsFailed(error) {
      console.error(error);
    }
  }
}

events.json

[{
    "day": "11/17/2016",
    "time": "09:45"
  }, {
    "day": "17/11/2016",
    "time": "16:50"
  }, {
    "day": "18/11/2016",
    "time": "11:25"
  }, {
    "day": "18/11/2016",
    "time": "12:30"
  }, {
    "day": "11/21/2016",
    "time": "16:10"
  }, {
    "day": "11/21/2016",
    "time": "17:25"
  }]

The view.

<div ng-app="demo">
  <div ng-controller="DefaultController as ctrl">
    <div class="form-group">
      <label>Event Date</label>
      <select ng-options="event as event.date for event in ctrl.data.events" ng-model="ctrl.event">
        <option value="">Select</option>
      </select>
    </div>
    <div class="form-group">
      <label>Event Time</label>
      <select ng-options="schedule as schedule.time for schedule in ctrl.data.schedules | filter: { date: ctrl.event.date}" ng-model="ctrl.schedule" ng-disabled="!ctrl.event">
        <option value="">Select</option>
      </select>
    </div>
  </div>
</div>

Note: If you don't want to create a data service then you can just put the function that transforms the source data as per your needs, in the controller and invoke it in the $http request's success callback.

$scope.submit = function() {
    ...
    $http.post(link, { username : $scope.data.username }).then(function (response) {
        $scope.response = processItems(response.data);
    });

    function processItems(events) {
        ...
    }
};
Abdul Mateen Mohammed
  • 1,864
  • 1
  • 12
  • 21
  • this is perfect, i'll try it and i hope this can solved my problem, thank you so much !! – Edoardo Nov 18 '16 at 15:47
  • the console retreive me an error: **Failed to load resource: the server responded with a status of 404 (Not Found) app.js:106 Objectconfig: Objectdata: "Cannot GET /events.json↵"headers: (name)status: 404statusText: "Not Found"__proto__: ObjectgetEventsFailed @ app.js:106** – Edoardo Nov 18 '16 at 15:57
  • You need to replace the 'events.json' with your api call from your question i.e. this url 'http://localhost/ShuttleFIX/api.php' if you're trying to get the mock data from 'events.json' please check if the file is present and it is in the proper folder based on the path you've specified in the $http request, in the above given e.g. both the script and events.json are in the same folder. Try to add breakpoints in the callbacks and see where the issue is. – Abdul Mateen Mohammed Nov 18 '16 at 17:57
  • i've tried to retreive data from "events.json" and form the server (localhost/ShuttleFIX/api.php) but in both cases i haven't retrieve nothing – Edoardo Nov 21 '16 at 08:41
  • @Edoardo, keep a debugger at the very beginning in the transformResponse function and check whether you're getting the data – Abdul Mateen Mohammed Nov 21 '16 at 12:27
  • yes, i get the data correctly @Abdoul Mateen Mohammed – Edoardo Nov 21 '16 at 12:53
  • Good, now check whether the content-type is matching with the content-type returned by the server if it isn't then please update the content-type in the condition and make sure the response is being processed to generate the data structure of your choice by the transformation function. The code in the above answer works with a valid JSON response. – Abdul Mateen Mohammed Nov 21 '16 at 13:33
  • how can i do this? – Edoardo Nov 21 '16 at 13:36
  • @Edoardo, when you're debugging the transformation function just write to console this value: headers("content-type") it will print the content-type of the response – Abdul Mateen Mohammed Nov 21 '16 at 13:38
  • is it possible that i received "headers is not defined"?? @Abdul Mateen Mohammed – Edoardo Nov 21 '16 at 13:42
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/128630/discussion-between-abdul-mateen-mohammed-and-edoardo). – Abdul Mateen Mohammed Nov 21 '16 at 13:53
  • there is still one question can you help me? http://chat.stackoverflow.com/rooms/128630/discussion-between-abdul-mateen-mohammed-and-edoardo – Edoardo Nov 21 '16 at 15:34
  • with the array that i received from the server i've this: **text/html; charset=UTF-8** – Edoardo Nov 22 '16 at 08:08
  • that's great, @Edoardo I recommend you a course https://www.codeschool.com/courses/discover-devtools it's free – Abdul Mateen Mohammed Nov 22 '16 at 12:47
0

I suggest you to use the MomentJS library to deal with dates.

Then, loop on your array, read the Day property, make your computation (with MomentJS you have some nice and easy to use functions to know if it's current day, in the past etc.) and add it to the proper array.

In this example, the array you receive from the server is stored in the variable data.

var firstArray = [], 
  secondArray = [], 
  thirdArray = [], 
  fourthArray = [];

data.forEach(function(entry) {
  var day = moment(entry.Day, "MM/DD/YYYY");
  /* your computation here to know in which array it'll go */
})
Valentin Coudert
  • 1,759
  • 3
  • 19
  • 44
0

first, the array format is not correct :) I made some little changes :

var arr = [
    { "Day": "11/17/2016", "time": "09:45"},
    { "Day": "17/11/2016", "time": "16:50"}, 
    { "Day": "18/11/2016", "time": "11:25"},
    { "Day": "18/11/2016", "time": "12:30"}, 
    { "Day": "11/21/2016", "time": "16:10"},
    { "Day": "11/21/2016", "time": "17:25"}
]

I declared after, 2 arrays :

var First = [];
var Second = [];

And finally I pushed what I want in the new arrays :

arr.forEach(function(item){
    First.push(item.Day);
    Second.push(item.time);
})
Mourad Idrissi
  • 3,455
  • 5
  • 17
  • 29
0

Use Array.prototype.reduce to create an object with day as key and times as the value array and get the required arrays from that - see demo below:

var array=[{"Day":"11/17/2016","time":"09:45"},{"Day":"17/11/2016","time":"16:50"},{"Day":"18/11/2016","time":"11:25"},{"Day":"18/11/2016","time":"12:30"},{"Day":"11/21/2016","time":"16:10"},{"Day":"11/21/2016","time":"17:25"}];

var result = array.reduce(function(prev,curr){
  prev[curr.Day] = prev[curr.Day] || [];
  prev[curr.Day].push(curr.time);
  return prev;
},{});

// list of days
console.log("Days: ", Object.keys(result));

// get times for each day by using date as a key
for(var key in result) {
  console.log(key + " => " + result[key]);
}
.as-console-wrapper{top:0;max-height:100%!important;}
kukkuz
  • 41,512
  • 6
  • 59
  • 95
0

Here is my suggestion, using Lodash to simplify although it can be done with just JS.

Also, note that the date formats are inconsistent so I tried to make sense of it by using DD/MM/YYYY format.

var arr = [
        { "Day": "17/11/2016", "time": "09:45"},
        { "Day": "17/11/2016", "time": "16:50"}, 
        { "Day": "18/11/2016", "time": "11:25"},
        { "Day": "18/11/2016", "time": "12:30"}, 
        { "Day": "21/11/2016", "time": "16:10"},
        { "Day": "21/11/2016", "time": "17:25"}
    ];
    
// Group the times by the date
var grouped = _(arr)
.groupBy('Day')
.mapValues(v => _.map(v, 'time'))
.mapKeys((v, k) => moment(k, 'DD/MM/YYYY').format('DD.MM.YYYY'))
.value();

// Massage the grouped times
var result = [_.keys(grouped)];
result.push.apply(result, _.values(grouped));

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.16.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
Nick Caballero
  • 944
  • 1
  • 8
  • 19
  • thank's for the reply, it works, i've only one questio, if you have seen my update i retreive the array that contains days and times from a server so can you help me for this and for have a form with two selects, the first where there are days and the second that change dinamically with the choice of the day that contains times. Thank's – Edoardo Nov 18 '16 at 14:23
0

You can create two arrays one for list of dates and another for list of timings as the data source for the two <select> elements from the source array which you're getting from the server, You'll need a property which will help in identifying the relationship b/w the dates and timings array i.e. the date property here.

Please check the below code snippet, the timings drop down list is filtered using the date property as filter: { date: ctrl.event.date}, I hope it will be of help to you.

angular
  .module('demo', [])
  .controller('DefaultController', DefaultController);

function DefaultController() {
  var vm = this;
  var events = [{
    "day": "11/17/2016",
    "time": "09:45"
  }, {
    "day": "17/11/2016",
    "time": "16:50"
  }, {
    "day": "18/11/2016",
    "time": "11:25"
  }, {
    "day": "18/11/2016",
    "time": "12:30"
  }, {
    "day": "11/21/2016",
    "time": "16:10"
  }, {
    "day": "11/21/2016",
    "time": "17:25"
  }];

  vm.data = processItems(events);

  function processItems(events) {
    var result = {
      events: [],
      schedules: []
    };

    var dates = [];
    for (var i = 0; i < events.length; i++) {
      if (dates.indexOf(events[i].day) === -1) {
        var date = events[i].day;
        dates.push(date);
        result.events.push({
          date: date
        });
      }

      result.schedules.push({
        date: events[i].day,
        time: events[i].time
      });
    }

    return result;
  }
}
.form-group {
  margin: 10px;
}
.form-group * {
  width: 100px;
}
.form-group label {
  float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demo">
  <div ng-controller="DefaultController as ctrl">
    <div class="form-group">
      <label>Event Date</label>
      <select ng-options="event as event.date for event in ctrl.data.events" ng-model="ctrl.event">
        <option value="">Select</option>
      </select>
    </div>
    <div class="form-group">
      <label>Event Time</label>
      <select ng-options="schedule as schedule.time for schedule in ctrl.data.schedules | filter: { date: ctrl.event.date}" ng-model="ctrl.schedule" ng-disabled="!ctrl.event">
        <option value="">Select</option>
      </select>
    </div>
  </div>
</div>

If you have control over the server code, I suggest you get the response JSON something like as shown below.

var data = {
  events: [
    { eventId: 1, eventDate: '11/17/2016' },
    { eventId: 2, eventDate: '12/18/2016' },
    { eventId: 3, eventDate: '12/21/2016' }
  ],
  timings: [{
    { eventId: 1, eventTime: '10:00' },
    { eventId: 1, eventTime: '12:30' },
    { eventId: 2, eventTime: '16:50' },
    { eventId: 3, eventTime: '17:50' }
  }]
};

Although you can fancy to use the source array you're getting for both the drop down lists as shown in the below e.g. I wouldn't recommended it though as it gets difficult over time to maintain when things start getting complex or changes to system happen.

angular
  .module('demo', [])
  .controller('DefaultController', DefaultController)
  .filter('unique', unique);

function DefaultController() {
  var vm = this;
  vm.events = [{
    "day": "11/17/2016",
    "time": "09:45"
  }, {
    "day": "17/11/2016",
    "time": "16:50"
  }, {
    "day": "18/11/2016",
    "time": "11:25"
  }, {
    "day": "18/11/2016",
    "time": "12:30"
  }, {
    "day": "11/21/2016",
    "time": "16:10"
  }, {
    "day": "11/21/2016",
    "time": "17:25"
  }];
}

function unique() {
  return function(input, key) {
    var unique = {};
    var uniqueList = [];
    for (var i = 0; i < input.length; i++) {
      if (typeof unique[input[i][key]] == "undefined") {
        unique[input[i][key]] = "";
        uniqueList.push(input[i]);
      }
    }
    return uniqueList;
  };
}
.form-group {
  margin: 10px;
}
.form-group * {
  width: 100px;
}
.form-group label {
  float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demo">
  <div ng-controller="DefaultController as ctrl">
    <div class="form-group">
      <label>Event Date</label>
      <select ng-options="event as event.day for event in ctrl.events | unique: 'day'" ng-model="ctrl.event">
        <option value="">Select</option>
      </select>
    </div>
    <div class="form-group">
      <label>Event Time</label>
      <select ng-options="schedule as schedule.time for schedule in ctrl.events | filter: { day: ctrl.event.day}" ng-model="ctrl.schedule" ng-disabled="!ctrl.event">
        <option value="">Select</option>
      </select>
    </div>
  </div>
</div>
Abdul Mateen Mohammed
  • 1,864
  • 1
  • 12
  • 21