chamPotato chamPotato - 1 month ago 11
AngularJS Question

Moving data between directive and controller

I am using ui-grid to upload a XLS file through a directive and push the data

I am trying to move data between my directive and controller (pretty new to angular). I have gone through a bunch of threads (this, this, this, and this) to try to understand how to use the &, @, =, $watch, and $observe, but I still do not understand how to move my data from the directive (which has a JSON object) to an array (myData) in my controller. If someone could please help me solve this problem...

Controller

.controller('ListCtrl', function ($scope, $state, $log, ServerRequest, $localStorage, $sessionStorage, uiGridConstants) {

var vm = this, c = console;
$scope.sortAlert = sortAlert;
$scope.myData = [
{
"alert": "2",
"firstName": "Rob",
"lastName": "McBob",
"dob": "03/12/1941",
"sex": "M",
"mi": "C",
"referralReason": "Morbid Obesity",
"userStatus": "Schedules",
"timeSched": "02:00PM",
"homeNum": "416-555-5555",
"cellNum": "905-555-5555",
"notes": "cool",
"uniqueId": "638768756304"
}
];


//this formats the row
$scope.highlightFilteredHeader = function( row, rowRenderIndex, col, colRenderIndex ) {
if( col.filters[0].term ){
return 'header-filtered';
} else {
return '';
}
};

//handles the functionality of the grid
$scope.gridOptions = {
enableFiltering: true,
onRegisterApi: function(gridApi){
$scope.gridApi = gridApi; //so we can use gridapi functions of ui-grid
//handler for clicking rows
gridApi.selection.on.rowSelectionChanged($scope, function(row){
var thisRow = gridApi.selection.getSelectedRows() //gets the clicked row object
$log.log(thisRow);
//creates new tab -> the tabby part itselfid="' + thisRow[0].uniqueId + '"
$('.ui.top.attached.tabular.menu').append('<a class="active item" style="border-radius: 0px !important; background-color: #4B6A89; font-family: Roboto; font-size: 16px; color: white; font-weight: 300; letter-spacing: 1.5px;" id="' + thisRow[0].uniqueId + '" data-tab="' + thisRow[0].uniqueId + '">' + thisRow[0].firstName + ' ' + thisRow[0].lastName + '<i id="' + thisRow[0].uniqueId + '" class="material-icons" style="position: relative; right: -60px; font-weight: 200;">clear</i></a>'); //add ui bottom - the body of the tab
$('.tab-container').append('<div id="' + thisRow[0].uniqueId +'" class="ui bottom attached tab segment" data-tab="' + thisRow[0].uniqueId + '">' + 'new page' + '</div>');
reinitializeTabs(); //jquery to add ui-semantic tabs functionality to new tabs

});
},
data: 'myData',
columnDefs: [
{
field: 'alert', displayName: 'ALERTS', headerCellClass: $scope.highlightFilteredHeader,
sort: {
direction: uiGridConstants.DESC,
priority: 1
}
},
{
field: 'firstName', displayName: 'FIRST NAME', headerCellClass: $scope.highlightFilteredHeader
},
{
field: 'lastName', displayName: 'LAST NAME', headerCellClass: $scope.highlightFilteredHeader
},
{
field: 'dob', displayName: 'DOB', headerCellClass: $scope.highlightFilteredHeader
},
{
field: 'referralReason', displayName: 'REFERRAL REASON', headerCellClass: $scope.highlightFilteredHeader
},
{
field: 'userStatus', displayName: 'STATUS', headerCellClass: $scope.highlightFilteredHeader
},
{
field: 'timeSched', displayName: 'TIME', headerCellClass: $scope.highlightFilteredHeader
},
{
field: 'homeNum', displayName: 'HOME #', headerCellClass: $scope.highlightFilteredHeader
},
{
field: 'cellNum', displayName: 'CELL #', headerCellClass: $scope.highlightFilteredHeader
},
{
field: 'mi', displayName: 'MI', headerCellClass: $scope.highlightFilteredHeader
},
{
field: 'sex', displayName: 'SEX', headerCellClass: $scope.highlightFilteredHeader
},
{
field: 'notes', displayName: 'NOTES', headerCellClass: $scope.highlightFilteredHeader
},
{
field: 'uniqueId', displayName: 'UNIQUE ID', headerCellClass: $scope.highlightFilteredHeader
}
]
};


});

})//end of controller


Directive

.directive("fileread", [function () {
return {
scope: {
opts: '@'
},
link: function ($scope, $elm, $attrs) {
$elm.on('change', function (changeEvent) {
var reader = new FileReader();

reader.onload =function (evt) {
$scope.$apply(function () {
var data = evt.target.result;

var workbook = XLSX.read(data, {type: 'binary'});

var headerNames = XLSX.utils.sheet_to_json(
workbook.Sheets[workbook.SheetNames[0]],
{ header: 1 }
)[0];

var data = XLSX.utils.sheet_to_json( workbook.Sheets[workbook.SheetNames[0]]);

// $scope.opts.columnDefs = [];
// headerNames.forEach(function (h) {
// $scope.opts.columnDefs.push({ field: h });
// });

$scope.opts.data = data;
console.log(data);
// addRows(data);
$elm.val(null);
//this is where we add the new data to the existing data

$scope.opts.data.push({
"alert": data[0].alert
, "firstName": data[0].firstName
, "lastName": data[0].lastName
, "dob": data[0].dob
, "referralReason": data[0].referralReason
, "userStatus": data[0].userStatus
, "timeSched": data[0].timeSched
, "homeNum": data[0].homeNum
, "cellNum": data[0].cellNum
, "mi": data[0].mi
, "sex": data[0].sex
, "notes": data[0].notes
, "uniqueId": data[0].uniqueId
});
});
};
reader.readAsBinaryString(changeEvent.target.files[0]);
});
}
}
}]); //end of directive

Answer

In your directive, declare reference to myData (can be any name):

scope: {
    myData: '=',
    opts: '='
}

Directive usage (myData is the object from your controller):

<fileread my-data="myData"></fileread>

Now $scope/scope in both the controller and directive point to the same resource.

@ is for one-way data-binding, hence the error your posted under comments.