2

So I'm trying to create a basic angular application that parses some CSV input, and fills a table with the parsed data.

You can see a plunker of what I'm trying to achieve here - http://plnkr.co/edit/6QFT4AcV4KpiSG23EdOS

Basically - as you can see - I have a <textarea> where the user will paste in some CSV, and the table below should then be filled with the data.

<div class="excelArea">
    <textarea name="excelData" ng-model="excelData"></textarea>
</div>

This is the javascript I have so far, but I'm struggling with a few things 1. Seperating the email from the name 2. Pushing the data back into the $scope.inviteList;

app.controller("InviteController", function($scope) {

    //Initliase objects
    $scope.excelData = "";
    $scope.errorMessage = "";
    $scope.inviteList = [];

    $scope.$watch("excelData", function() {

        var lines, lineNumber, data, length;

        lines = $scope.excelData.match(/[^\r\n]+/g);
        lineNumber = 0;

        for (var i = lines.length - 1; i >= 0; i--) {

            l = lines[i];
            lineNumber++;
            data = l.split(/\t/);

            var email = ? ? ?
            var name = ? ? ?

            $scope.inviteList.push({
                name: name,
                email: email,
                status: "not sent"
            });

        };

    });

});

Some basic information:

The CSV will be two columns (name, email) and will look like this:

John Thompson,[email protected]
Robin Peters, [email protected]
Bill Bob, [email protected]
1
  • Note that parsing a CSV is not just splitting on the separator, if you want to fully support the CSV format use a 'real' parser (for example papaparse.com) Commented Oct 7, 2015 at 14:24

3 Answers 3

3

Many problems in your code :

  • You could juste use split on your input instead of regexes, it makes everything easier
  • Your HTML isn't valid td should be inside tr and not the other way around
  • Your array was never cleared
  • Your bindings inside ng-repeat didn't use variable i defined here : i in inviteList
  • You should avoid unscoped variables (without var keyword) whenever possible

Otherwise, when you split a string, just access the splitted elements through their index.

Corrected code :

JS

$scope.$watch("excelData", function() {
    var lines, lineNumber, data, length;
    $scope.inviteList = [];
    lines = $scope.excelData.split('\n');
    lineNumber = 0;
    for (var i = lines.length - 1; i >= 0; i--) {
        l = lines[i];

        lineNumber++;
        data = l.split(',');

        var name = data[0];
        var email = data[1];

        $scope.inviteList.push({
            name: name,
            email: email,
            status: "not sent"
        });
    }
});

HTML

  <table>
    <tr>
      <th>Name</th>
      <th>Email</th>
      <th>Status</th>
    </tr>
    <tr ng-repeat="i in inviteList">
      <td>{{i.name}}</td>
      <td>{{i.email}}</td>
      <td>{{i.status}}</td>
    </tr>
  </table>

Your code (especially JS) can still be improved a lot and i encourage you to read docs/tutorials more.

And here is the plunker to your working code.

Sign up to request clarification or add additional context in comments.

Comments

1

I would create a filter to parse the data and reuse it anywhere I want it to. Logic:

app.controller('MainCtrl', function($scope, $filter) {
  $scope.data = 'John Thompson,[email protected]\nRobin Peters, [email protected]\nBill Bob, [email protected]';

  $scope.$watch('data', function(val){
    $scope.inviteList = $filter('csvToObj')(val);
  });
});

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({
        name: o[0],
        email: o[1],
        status: "not sent"
      });
    });
    return obj;
  };
});

Sample Demo:http://plnkr.co/edit/SOtMMLft3amlVm4RROd0?p=preview

1 Comment

Thanks! Works nicely, changes my structure a bit , but this is much better!
1

When you split a string, the return value is an array. I believe that you only have to access the correct indexes of the data array:

app.controller("InviteController", function($scope) {

    //Initliase objects
    $scope.excelData = "";
    $scope.errorMessage = "";
    $scope.inviteList = [];

    $scope.$watch("excelData", function() {

        var lines, lineNumber, data, length;

        lines = $scope.excelData.match(/[^\r\n]+/g);
        lineNumber = 0;

        for (var i = lines.length - 1; i >= 0; i--) {

            l = lines[i];
            lineNumber++;
            data = l.split(/\t/);

            var email = data[1];
            var name = data[0];

            $scope.inviteList.push({
                name: name,
                email: email,
                status: "not sent"
            });

        };

    });

});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.