Validate CSV file in angularJs - angularjs

I have a csv file which contains two columns store_id and store_name.When the user uploads a csv file I need to validate the file i.e check if first column is Integer(store_id) and second column is String(store_name).Can you help how to read and retrieve the content and validate the file?
Thanks

Try this code
my csv file
store_id,store_name
01,"First point"
02,"Second point"
03,"Third point"
var demo = angular.module('demo', []);
demo.controller('loadData', function($scope,$rootScope,$http){
$scope.uploadData = function() {
var uploaded=$scope.fileContent;
$scope.processData(uploaded);
};
$scope.processData = function(allData) {
var filteredData = allData.split(/\r\n|\n/);
var headers = filteredData[0].split(',');
var final = [];
for ( var i = 0; i < filteredData.length; i++) {
if (!filteredData[i]=="") {
var data = filteredData[i+1].split(',');
if (isNaN(data[0])==false && isNaN(data[1])==true) {
final.push(data);
console.log("Valid CSV");
}
else{
console.log("Not Valid CSV");
}
}
}
$scope.data = final;
};
});
demo.directive('fileReader', function() {
return {
scope: {
fileReader:"="
},
link: function(scope, element) {
$(element).on('change', function(changeEvent) {
var files = changeEvent.target.files;
if (files.length) {
var r = new FileReader();
r.onload = function(e) {
var contents = e.target.result;
scope.$apply(function () {
scope.fileReader = contents;
});
};
r.readAsText(files[0]);
}
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js"></script>
<div ng-app='demo'>
<div ng-controller='loadData'>
<input type="file" file-reader="fileContent" />
<button ng-click='uploadData($event)' >upload</button>
<div>{{fileContent}}</div>
<table>
<tr ng-repeat="x in data">
<td ng-repeat="y in x">{{ y }}</td>
</tr>
</table>
</div>
</div>

document.getElementById('csvUpload').onchange = function(){
var file = this.files[0];
var storeId = [],storeName = [],line,flag = 1;
var reader = new FileReader();
reader.onload = function(progressEvent){
var lines = this.result.split('\n');
for(var iterator = 0; iterator < lines.length-1; iterator++){
line = lines[iterator].split(',');
storeId.push(line[0]);
storeName.push(line[1]);
}
var result = !storeId.some(isNaN);
for(var iterator = 0; iterator < storeName.length; iterator++) {
console.log(typeof storeName[iterator]);
if(typeof storeName[iterator] !== "string"){
flag = 0;
break;
}
}
if(result === false || flag === 0) {
var alert = mdDialog.alert({
textContent: 'Please select a valid csv file',
ok: 'Close'
});
mdDialog.show( alert );
}
};
reader.readAsText(file);
}

you may try this component
https://www.import-javascript-angular-xlsx-csv-validator.com/
it validates that and more

Related

The ng-repeat array is updating table data for the first time i'm selecting value, but its not updating the table data only once

I'm trying to update the table view depending on select option. The table view is updating only once, when i select the option second time the view is not updating, I'm not getting what's the problem. please help me solve this..
here is app.js
$scope.User = {};
$scope.arr = [];
$scope.loaddata = function(User) {
$scope.User.site = layouts;
AllServices.teamAllDataFunction1(User)
.then(function(response) {
$scope.User.data=response.data;
});
};
$scope.getdatalayoutwise = function(User) {
var total = 0;
var total1 = 0;
for (var i = 0; i < ($scope.User.data).length; i++) {
if($scope.User.data[i].Layout == $scope.User.selectedSite) {
total += parseInt($scope.User.data[i].dp_inst_pending);
$scope.arr.push($scope.User.data[i]);
}
}
for (var j = 0; j < ($scope.User.data1).length; j++) {
if($scope.User.data1[j].Layout == $scope.User.selectedSite) {
total1 += parseInt($scope.User.data1[j].DP_Inst_Pending);
}
}
$scope.User.teamTotal = total;
$scope.User.personalTotal = total1;
$scope.data = [$scope.User.teamTotal, $scope.User.personalTotal];
$scope.totamnt = parseInt($scope.User.personalTotal) + parseInt($scope.User.teamTotal);
$scope.User.totalamount = $filter('translate')('totalpending') + ": " + $filter('currency')($scope.totamnt, "");
$scope.User.data = $scope.arr;
};
here is html
<select name="site" ng-model="User.selectedSite" ng-change="getdatalayoutwise(User)">
<option value="">--{{'selectsite_message' | translate}}--</option>
<option ng-repeat= "option in User.site" value="{{option.Layout}}">{{option.Layout}}</option>
</select>
<table ng-table>
<tr>
<th>advisor_name</th>
<th>totalpending</th>
</tr>
<tr ng-repeat="data in User.data | filter : {Layout: User.selectedSite}: true" ng-if="data.dp_inst_pending">
<td class="ui-helper-center"><a ng-click="advisorDetails($index, data, User)">{{data.AdvisorName}}</a></td>
<td>{{data.dp_inst_pending | currency:"₹":0}}</td>
</tr>
</table>
you need to use $scope.$apply() :
$scope.getdatalayoutwise = function(User) {
$scope.$apply(function () {
var total = 0;
var total1 = 0;
for (var i = 0; i < ($scope.User.data).length; i++) {
if($scope.User.data[i].Layout == $scope.User.selectedSite) {
total += parseInt($scope.User.data[i].dp_inst_pending);
$scope.arr.push($scope.User.data[i]);
}
}
...
});
}
https://www.grafikart.fr/formations/angularjs/apply-watch-digest
Change your function to this
$scope.loaddata = function(User) {
$scope.User.data = [];
$scope.User.site = layouts;
AllServices.teamAllDataFunction1(User)
.then(function(response) {
$scope.User.data=response.data;
});
and add a ng-if
<table ng-table ng-if="User.data.length">
<tr>
<th>advisor_name</th>
<th>totalpending</th>
</tr>
<tr ng-repeat="data in User.data | filter : {Layout: User.selectedSite}: true" ng-if="data.dp_inst_pending">
<td class="ui-helper-center"><a ng-click="advisorDetails($index, data, User)">{{data.AdvisorName}}</a></td>
<td>{{data.dp_inst_pending | currency:"₹":0}}</td>
</tr>
</table>
Add this as the first line in getdatalayoutwise () function:
$scope.arr = [];
got it working by just doing following
$scope.safeApply = function(fn) {
var phase = this.$root.$$phase;
if(phase == '$apply' || phase == '$digest') {
if(fn && (typeof(fn) === 'function')) {
fn();
}
} else {
this.$apply(fn);
}
};
$scope.getdatalayoutwise = function(User) {
var total = 0;
var total1 = 0;
for (var i = 0; i < ($scope.User.data).length; i++) {
if($scope.User.data[i].Layout == $scope.User.selectedSite) {
total += parseInt($scope.User.data[i].dp_inst_pending);
$scope.arr.push($scope.User.data[i]);
}
}
...
$scope.safeApply (function () {
$scope.User.data = $scope.arr;
});
};

Controller function not applying to ng-include file

I am trying to use the "minisCtrlOverall" controller in my ng-include file, but none of the functionality in my controller works for the included file unless I put ng-controller in the actual overall.html file. What I am trying to do is access the "ring-fill" class that is in my overall.html file from my controller. I want to add the class "active" too all "ring-fills" but its not working. I'm guessing this isn't working because the included files comes after the controller runs? Anyone know how I can fix this?
Controller:
angular.module('ciscoImaDashboardAdmin',[])
.controller('minisCtrlOverall', function ($scope, $rootScope, dummyData) {
$scope.overallOn = true;
$scope.switchView = function(element) {
var value = element.target.attributes['value'].value;
if(value == "overall") {
$scope.overallOn = true;
$scope.swimlaneOn = false;
}
else if(value == "swimlane") {
$scope.swimlaneOn = true;
$scope.overallOn = false;
}
};
var totalRings = 9;
var maxScore = 10;
var data_overall = {
average_score: 6
}
var ringToHighlight = Math.floor((data_overall.average_score/maxScore)*totalRings); //round down
var i = 0;
var rings = [];
var ringClass = 'path.ring-fill:not(.ring-border)';
$(ringClass).each(function(){
rings.push($(this)[0]);
});
while( i < ringToHighlight) {
fillPath(i);
i = i + 1;
}
function fillPath(i) {
if(i < ringToHighlight) {
var selectedRing = $(rings[i]);
selectedRing.attr("class", "ring-fill active");
}
}
});
HTML:
<div class="row mini" ng-show="overallOn" ng-controller="minisCtrlOverall">
<div class="col-sm-3">
<div ng-include="'svgs/overall.html'"></div>
</div>
</div>

Not able to set column width in angular datatables

var app = angular.module('tableTest', ['datatables']);
app.controller('TableCtrl',function ($scope,$compile,DTOptionsBuilder, DTColumnBuilder) {
$scope.showUpdateForm = function(code,reason,startTime,endTime,transactionGroup,geoGroup,transactionGroup) {
$scope.$parent.code = code;
$scope.$parent.reason = reason;
$scope.$parent.startTime = startTime.split(' ')[1].substring(0,startTime.split(' ')[1].lastIndexOf(':'));
$scope.$parent.endTime = endTime.split(' ')[1].substring(0,endTime.split(' ')[1].lastIndexOf(':'));
$scope.$parent.startDate = startTime.split(' ')[0];
$scope.$parent.endDate = endTime.split(' ')[0];
$scope.$parent.transactionGroup = transactionGroup;
$scope.$parent.geoGroup = geoGroup;
$scope.$parent.group = transactionGroup;
$scope.$parent.getGeographyList();
$scope.$parent.getTransactionsList();
}
var vm = this;
vm.dtOptions = DTOptionsBuilder.newOptions()
.withOption('ajax', {
url: '<some url>',
type: 'GET'
})
.withDataProp('data')
.withOption('serverSide', true)
.withOption('createdRow', function(row, data, dataIndex) {
$compile(angular.element(row).contents())($scope);
})
.withOption('responsive', true).withOption('bAutoWidth', false)
.withPaginationType('full_numbers');
vm.dtColumns = [
DTColumnBuilder.newColumn('group').withTitle('Group').withOption('bSortable',true),
DTColumnBuilder.newColumn('startTime').withTitle('Start').withOption('bSortable',true),
DTColumnBuilder.newColumn('endTime').withTitle('End').withOption('bSortable',true),
DTColumnBuilder.newColumn('status').withTitle('Status').withOption('bSortable',true),
DTColumnBuilder.newColumn('reason').withTitle('Reason').withOption('bSortable',true).withOption('sWidth', '20%'),
DTColumnBuilder.newColumn('transactionGroup').withTitle('Transaction Group').withOption('bSortable',true),
DTColumnBuilder.newColumn('geoGroup').withTitle('Geo Group').withOption('bSortable',true),
DTColumnBuilder.newColumn('group').withTitle('Current Status').renderWith(function(data, type, full, meta) {
var arr = full.endTime.split(/-|\s|:/);
var endTime = new Date(arr[0], parseInt(arr[1])-1, arr[2], arr[3], arr[4], arr[5]);
arr = full.startTime.split(/-|\s|:/);
var startTime = new Date(arr[0], parseInt(arr[1])-1, arr[2], arr[3], arr[4], arr[5]);
var currentTime = new Date();
var color = ['#2196F3','#009688'];
var currentStatus = ['INACTIVE','ACTIVE']
var index;
if(startTime.getTime() <= currentTime.getTime() && currentTime.getTime() <= endTime.getTime()) {
index = 1;
} else {
index = 0;
}
return '<span style="background : '+color[index]+';color: #FFF;font-weight: 500;" class="currentStatus"> '+currentStatus[index]+' </span>';
}).notSortable(),
DTColumnBuilder.newColumn('code').withTitle('').notSortable().renderWith(function(data, type, full, meta) {
return '<div class="btn-group" > <label class="btn btn-primary"><input type="radio" name="blockedTransaction" ng-click="showUpdateForm(\''+full.code+'\',\''+full.reason+'\',\''+full.startTime+'\',\''+full.endTime+'\',\''+full.transactionGroup+'\',\''+full.geoGroup+'\',\''+full.transactionGroup+'\')" ng-model="blockedTransaction" data-toggle="modal" data-target="#updateForm" data-whatever="#getbootstrap" >EDIT</label></div>';
})
];});
The above code is my table controller. The problem is that I am not able to set the column width. When there is a lot of data for a column, the table resizes and it goes out of its page. What is wrong in the code. What is right key value pair to be put in "withOption" so that it sets the width of the column properly.
Link to Datatables plugin and
Link to Datatables + Angular plugin
Since your test is using a long word without any space, you will need to use the word-break.
See this pen for example:
.dataTable td {
word-break: break-all;
}

CSV upload filtering in AngularJS

I am currently adding a CSV email-list option to an existing AngularJS-based site. I use Papa Parse to parse the CSV straight to objects. What I need to do is have these results add up to the HTML and filter them so that only the email addresses will appear in the results, which will then later be counted for sending. How can I filter a CSV parse reult so that it only displays email addresses and ignores all the other values? Naturally, this would have to be done using just Angular to avoid conflicts.
Here's the Papa Parse section:
$('input[type=file]').parse({
config: {header: true,
step: function(results, handle) {
rows = _.union(rows, results.data);
console.log("Row data:", results.data);
console.log("Row errors:", results.errors);
// Define HTML output
//
for (var i = 0; i < $files.length; i++) {
var file = $files[i];
}
$.each(results.data, function(i, el) {
var row = $('<ng-form ng-repeat="row in rows"/>');
row.append($('').text(i));
$.each(el, function(j, cell) {
if (cell !== "")
row.append($('<td type="text" class="form-control csv-form medium" ng-model="row.email"></td>').text(cell));
});
$("#results").append(row);
});
}
}
});
function FileUploadCtrl(scope) {
scope.setFiles = function(element) {
scope.$apply(function(scope) {
console.log('files:', element.files);
// Turn the FileList object into an Array
scope.files = []
for (var i = 0; i < element.files.length; i++) {
scope.files.push(element.files[i])
}
scope.progressVisible = false
});
};
scope.uploadFile = function() {
var fd = new FormData()
for (var i in scope.files) {
fd.append("uploadedFile", scope.files[i])
}
var xhr = new XMLHttpRequest()
xhr.upload.addEventListener("progress", uploadProgress, false)
xhr.addEventListener("load", uploadComplete, false)
xhr.addEventListener("error", uploadFailed, false)
xhr.addEventListener("abort", uploadCanceled, false)
xhr.open("POST", "/fileupload")
scope.progressVisible = true
xhr.send(fd)
}
}
}
);
},
This should be the HTML part:
<div ng-file-select="onFileSelect($files, angular.element(this).scope())" data-multiple="true" ng-list ng-model="csv" id="fileToUpload" title="Select file" ng-change="angular.element(this).scope().setFiles(this)">
<i class="fa fa-upload"></i> {{ 'Import CSV' | Translator }}

{{numPages}} not being calculated by pagination directive

I was under the impression with the pagination directive that the {{numPages}} value would be calculated by the directive. It isn't returning anything for me.
Is there anything I am missing to get this working properly? I don't want to have to calculate it, if the directive is supposed to be doing this for me. Otherwise paging is working great.
<pagination
total-items="totalItems"
ng-model="currentPage"
max-size="maxSize"
items-per-page="itemsPerPage"
class="pagination-sm"
boundary-links="true" rotate="false">
</pagination>
<table class="table table-striped">
<tr>
<td style="width:150px;">GPT ID</td>
<td style="width:250px;">Therapy Area</td>
<td style="width:450px;">GPT Description</td>
<td style="width:150px;">Actions</td>
</tr>
<tr ng-repeat="prGpt in prGpts | orderBy:['therapyArea.therapyArea','gptDesc'] | startFrom:(currentPage -1) * itemsPerPage | limitTo: itemsPerPage">
<td>{{prGpt.id}}</td>
<td>
<span ng-if="!prGpt.editMode">{{prGpt.therapyArea.therapyArea}}</span>
<span ng-if="prGpt.editMode && !createMode">
<select class="form-control" style="width:150px;" ng-model="selectedGpt.therapyArea" ng-options="item as item.therapyArea for item in therapyAreas"/>
</span>
</td>
<td>
<span ng-if="!prGpt.editMode">{{prGpt.gptDesc}}</span>
<span ng-if="prGpt.editMode && !createMode"><input class="form-control" type="text" style="width:400px;" ng-model="selectedGpt.gptDesc" /></span>
</td>
<td>
<span ng-if="!prGpt.editMode" class="glyphicon glyphicon-pencil" ng-click="copySelectedGpt(prGpt);beginEditGpt()"/>
<span ng-if="prGpt.editMode && !createMode" class="glyphicon glyphicon-floppy-disk" ng-click="saveEditGpt()"/>
<span ng-if="prGpt.editMode && !createMode" class="glyphicon glyphicon-thumbs-down" ng-click="cancelEditGpt()"/>
<span ng-if="!prGpt.editMode && !createMode" class="glyphicon glyphicon-remove-circle" ng-click="copySelectedGpt(prGpt);openDeleteDialog()"/>
<span><a ng-href="#!pr/gptProjects/{{prGpt.id}}">Edit Projects</a>
</span>
</tr>
</table>
<br/>
<pre>Page: {{currentPage}} / {{numPages}}</pre>
</div>
controller:
// GPT List Controller
.controller('prGPTCtrl',['$scope', '$modal', '$dialog', 'Restangular', 'prTAService', 'prGPTService', function($scope, $modal, $dialog, Restangular, prTAService, prGPTService) {
// window.alert('prGPTCtrl');
$scope.prGpts = {};
$scope.therapyAreas = {};
$scope.createMode = false;
$scope.selectedGpt = {};
$scope.newGpt = {};
// pagination
$scope.currentPage = 1;
$scope.itemsPerPage = 10;
$scope.maxSize = 20;
$scope.totalItems = $scope.prGpts.length;
Restangular.setBaseUrl('resources/pr');
//call the TA service to get the TA list for the drop down lists
//and then get the gpt list once successful
prTAService.getTAs().then(function(tas) {
$scope.therapyAreas = tas;
prGPTService.getGPTs().then(function(gpts) {
//window.alert('prGPTCtrl:getGPTs');
$scope.prGpts = gpts;
});
});
$scope.$watch('prGpts.length', function(){
$scope.totalItems = $scope.prGpts.length;
});
/*
* Take a copy of the selected GPT to copy in
*/
$scope.copySelectedGpt = function(prGpt) {
$scope.selectedGpt = Restangular.copy(prGpt);
};
$scope.beginEditGpt = function() {
var gpt = {};
var ta = {};
var gpt;
for(var i = 0; i < $scope.prGpts.length;i++) {
gpt = $scope.prGpts[i];
gpt.editMode = false;
}
var index = _.findIndex($scope.prGpts, function(b) {
return b.id === $scope.selectedGpt.id;
});
gpt = $scope.prGpts[index];
gpt.editMode = true;
var taIndex = _.findIndex($scope.therapyAreas, function(b) {
return b.id === $scope.selectedGpt.therapyArea.id;
});
ta = $scope.therapyAreas[taIndex];
$scope.selectedGpt.therapyArea = ta;
$scope.createMode = false;
};
$scope.cancelEditGpt = function() {
var gpt;
for(var i = 0; i < $scope.prGpts.length;i++) {
gpt = $scope.prGpts[i];
gpt.editMode = false;
}
var index = _.findIndex($scope.prGpts, function(b) {
return b.id === $scope.selectedGpt.id;
});
$scope.selectedGpt = null;
$scope.prGpts[index].editMode = false;
};
$scope.saveEditGpt = function() {
$scope.selectedGpt.save().then(function (gpt) {
// find the index in the array which corresponds to the current copy being edited
var index = _.findIndex($scope.prGpts, function(b) {
return b.id === $scope.selectedGpt.id;
});
$scope.prGpts[index] = $scope.selectedGpt;
$scope.prGpts[index].editMode = false;
$scope.selectedGpt = null;
},
function(err) {
window.alert('Error occured: ' + err);
}
);
};
// create a new GPT
$scope.createGpt = function() {
$scope.createMode = true;
var gpt;
for(var i = 0; i < $scope.prGpts.length;i++) {
gpt = $scope.prGpts[i];
gpt.editMode = false;
}
};
$scope.saveNewGpt = function() {
Restangular.all('/gpt/gpts').post($scope.newGpt).then(function(gpt) {
$scope.newGpt = {};
$scope.prGpts.push(gpt);
$scope.createMode = false;
// window.alert('created new GPT ' + gpt.gptDesc + ' with id ' + gpt.id);
});
};
$scope.openDeleteDialog = function() {
var title = "Please confirm deletion of GPT " + $scope.selectedGpt.gptDesc;
var msg = "<b>Delete GPT? Please confirm...</b>";
var btns = [{result:'CANCEL', label: 'Cancel'},
{result:'OK', label: 'OK', cssClass: 'btn-primary'}];
$dialog.messageBox(title, msg, btns, function(result) {
if (result === 'OK') {
$scope.deleteGpt();
}
});
};
$scope.deleteGpt = function() {
$scope.selectedGpt.remove().then(function() {
$scope.prGpts = _.without($scope.prGpts, _.findWhere($scope.prGpts, {id: $scope.selectedGpt.id}));
$scope.selectedGpt = null;
},
function() {
window.alert("There was an issue trying to delete GPT " + $scope.selectedGpt.gptDesc);
}
);
};
}]);
I have a startFrom filter.
.filter('startFrom', function () {
return function (input, start) {
if (input === undefined || input === null || input.length === 0
|| start === undefined || start === null || start.length === 0 || start === NaN) return [];
start = +start; //parse to int
try {
var result = input.slice(start);
return result;
} catch (e) {
// alert(input);
}
};
})
Regards
i
Looks like you're just missing num-pages="numPages" on your <pagination> tag. Essentially you have to provide a variable to pagination in which to return the number of pages. This is done via num-pages
<pagination
num-pages="numPages" <!-- Add this here -->
total-items="totalItems"
ng-model="currentPage"
max-size="maxSize"
items-per-page="itemsPerPage"
class="pagination-sm"
boundary-links="true" rotate="false">
</pagination>

Resources