aknorw
aknorw

Reputation: 288

Parsing a CSV file provided by an input in Angular

I'm creating a webapp which features uploads of .csv file.

Instead of uploading the whole file on my server, then adding every lines in a table thanks to PHP, I'd like to parse the file in Angular, then add parsed lines (thanks to Restangular). This way, I should be able to retrieve some "errors" before uploading them (or not).

In a view, I've created a simple file input, with a directive called file (source : http://angularjstutorial.blogspot.fr/2012/12/angularjs-with-input-file-directive.html)

<input type="file" data-file="param.file" />

The filedirective :

app.directive('file', function(){
  return {
    scope: {
      file: '='
    },
    link: function(scope, el, attrs){
      el.bind('change', function(event){
        var files = event.target.files;
        var file = files[0];
        scope.file = file ? file.name : undefined;
        scope.$apply();
      });
    }
  };
});

This way, I can retrieve when the user chooses a file. Unfortunately, I'm getting only the file name.

I'd like to parse the csv in a string, which i'll split thanks to this filter (source : parsing CSV in Javascript and AngularJS) :

app.filter('csvToObj',function(){
  return function(input){
    var rows=input.split('\n');
    var obj=[];
    angular.forEach(rows,function(val){
      var o=val.split(';');
      obj.push({
        designation:o[1],
        ...
        km:o[11]
      });
    });
    return obj;
  };
});

How can I retrieve the data in the csv file provided by the input instead of the file name ?

Thanks in advance.

Upvotes: 9

Views: 16011

Answers (1)

aknorw
aknorw

Reputation: 288

Ok, I found the solution by searching on existing modules to upload files. I just post it here if this interests someone.

In the view, I've changed the directive to trigger the event :

<input type="file" file-change="handler($event,files)" ng-model="MyFiles" />

The directive is now :

app.directive('fileChange',['$parse', function($parse){
  return{
    require:'ngModel',
    restrict:'A',
    link:function($scope,element,attrs,ngModel){
      var attrHandler=$parse(attrs['fileChange']);
      var handler=function(e){
        $scope.$apply(function(){
          attrHandler($scope,{$event:e,files:e.target.files});
        });
      };
      element[0].addEventListener('change',handler,false);
    }
  }
}]);

In the controller (don't forget to add $filter in the controller if you want to use it) :

$scope.MyFiles=[];

$scope.handler=function(e,files){
    var reader=new FileReader();
    reader.onload=function(e){
        var string=reader.result;
        var obj=$filter('csvToObj')(string);
        //do what you want with obj !
    }
    reader.readAsText(files[0]);
}

The filter is still the same (except I've shifted the rows array to not import the header of my csv files).

Upvotes: 15

Related Questions