how to access angular $scope from a javascript function - javascript

i have added a functionality to parse a CSV file in javascript. I want to assign the parsed data to $scope.data.arr. Currently, the below code gives error "Uncaught ReferenceError: scope is not defined". I am newbie to AngularJS and I have followed the official angular tutorials.
The code is:
application.js
'use strict';
/* Application module */
var ddvApp = angular.module('ddvApp', ['ddvControllers']);
dataController.js
'use strict';
/*Data Controller*/
var ddvControllers = angular.module('ddvControllers', []);
ddvControllers.controller('DataController', ['$scope', function($scope){
$scope.data = {}; //created a empty data object.
}]);
read-csv.js
function handleFiles(files) {
// Check for the various File API support.
if (window.FileReader) {
// FileReader are supported.
getAsText(files[0]);
}
else {
alert('FileReader are not supported in this browser.');
}
}
function getAsText(fileToRead) {
var reader = new FileReader();
// Read file into memory as UTF-8
reader.readAsText(fileToRead);
// Handle errors load
reader.onload = loadHandler;
reader.onerror = errorHandler;
}
function loadHandler(event) {
var csv = event.target.result;
scope.data.arr = processData(csv); //this is the line of code where i want to assign the parsed data to the angularjs $scope.
}
function processData(csv) {
var allTextLines = csv.split(/\r\n|\n/);
var lines = [];
for (var i = 0; i < allTextLines.length; i++) {
var data = allTextLines[i].split(',');
var arr = [];
for (var j = 0; j < data.length; j++) {
arr.push(data[j].trim());
}
lines.push(arr);
}
return lines;
}
function errorHandler(event) {
if(event.target.error.name == "NotReadableError") {
alert("Cannot read file !");
}
}
--UPDATE Problem Statement.
The handleFiles() function is called whenever user selects a new csv file to be parsed.
html code:
<input type="file" id="csvFileInput" onchange="handleFiles(this.files)" accept=".csv">
I firstly implemented the code to parse the CSV in javascript. I am using this data to render a graph on html canvas. I wanted a functionality where the user just selects a different csv file with updated data and the graph should update itself without further inputs. I added angularjs because (in future implementations) the file and graph need to be saved to a db. Also, some data can be requested from server instead of user loading it using a csv file.

While you can get acccess to the $scope via angular's element() function it looks like this is code that would be better put into an angular service.
If doing that is for some reason not an option, you need a reference to a DOM element that belongs to your controller.
Once you have that, you can do
angular.element(myDomElement).scope()
and that should give you a reference.
You can also use element.find() with css selectors but be aware that if you have not loaded JQuery you're left with a limited set of selectors (tag-names only).
See Docs for angular.element

What should be done is to copy all the JavaScript from read-csv.js and put it into dataController.js below this line:
$scope.data = {}; //created a empty data object.
define arr as an array:
$scope.data = {
arr: []
};
add a '$' in front of scope so that line should be:
$scope.data.arr = processData(csv);
This should fix the issue.

The proper way to do this is to put the functions in your read-csv.js file into a service, and then handle events using $rootScope.broadcast and $scope.$on.
So it may look something like:
module.factory('readCsv' ['$rootScope', function(rootScope){
var readCsv = {};
// load readCsv with read-csv.js functions
readCsv.loadHandler = function(event){
var csv = readCsv.processData(event.target.result);
$rootScope.$broadcast('$csvEvent', csv);
};
return readCsv;
}]).controller('DataController', ['$scope', function($scope){
$scope.data = {};
$scope.$on('$csvEvent', function(csv){
$scope.data.arr = csv;
};
}]);

Related

Fetch data from multiple sheets using Google app script

Trying to fetch data from multiple spreadsheet's. All Sheet's are stored in same folder. Have to fetch data in one master sheet from only specific files by file name. I have written below script. It's working fine if we enter only one file name in specified range (in master sheet tab) (getSheetByName) but showing error while trying to fetch data for multiple files.
Showing error - "TypeError: Cannot read property 'length' of undefined"
Below is Script -
function get_compiled_data() {
var filelist = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("FileName");
var filelists = filelist.getRange("A2:A").getValues();
var folder = DriveApp.getFolderById("1li9hBP_W5gPkb_ASKqin4j1ZGEn1Gvji");
var fileindex = folder.getFilesByName(filelists);
var file;
var filetype;
var sheetID;
var collect_data = [];
var data;
while (fileindex.hasNext()) {
file = fileindex.next();
filetype = file.getMimeType();
if (filetype === "application/vnd.google-apps.spreadsheet"){
sheetID = file.getId();
data = getData(sheetID);
data = data.map(function(r){return r.concat([file.getName()]);});
collect_data = collect_data.concat(data);
}
}
var target = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Compiled_Data");
target.getRange("A2:AX").clearContent();
target.getRange(2, 1, collect_data.length, collect_data[0].length).setValues(collect_data);
}
function getData (sheetID) {
var sheet = SpreadsheetApp.openById(sheetID);
var tab = sheet.getSheets()[0];
var data = tab.getRange("A3:AX" + tab.getLastRow()).getValues();
return data;
}
Issue:
You are providing a 2D array to getFilesByName(name), when you should be providing a string. Because of this, the code never enters the while block and collect_data remains an empty array, causing collect_data[0] to be undefined, and producing the observed error when trying to access its length.
When you were looking for a single file name you were probably using getValue(), which retrieves a single value, which can be a string, which can be used in getFilesByName. getValues() returns a 2D array instead, so you should adapt your code so that it iterates through each value returned by getValues().
Solution:
Edit the getValues() line and wrap all the actions made from getFilesByName inside a loop the following way:
function get_compiled_data() {
var filelist = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("FileName");
var filelists = filelist.getRange(2, 1, filelist.getLastRow() - 1).getValues();
var folder = DriveApp.getFolderById("FOLDER-ID");
filelists.forEach(fileName => {
var fileindex = folder.getFilesByName(fileName[0]);
// Rest of code
});
});
Reference:
getValues()
getValue()

Angular load data from server and publish in controllers

I want to grab some JSON Files with its content and make it available for other controllers. For this I know that I should create a factory that grabs the json files. My problem is that I dont know how to get the factory to return deityData.
Here is my Code that i want in a factory:
app.controller("dataContainer", function($scope,$http){
$http.get("./data/deitys/data.json").then(function (response) {
$scope.myData = response.data;
for(var i = 0; i < $scope.myData["deitys"].length;i++){
var dataString = "./data/deitys/" + $scope.myData["deitys"][i] +".json";
$http.get(dataString).then(function (response_) {
var deityData = response_.data;
$scope.deitys[deityData.deityName] = deityData;
});
}
});
Let's create a service for this, say deityService.
angular.service("deityService", () => {
this.deityData = undefined;
});
In all those controllers who want that data, add deityService as a dependency.
When you are done fetching data in your dataContainer controller, set deityData like this and emit an event that will let all others know that data has been set.
this.deityService.deityData = fetched_data;
this.deityService.emit("DEITY_DATA_SET");
Add a listener to all those controller for event
this.deityService.on("DEITY_DATA_SET",() => {
// now you can do console.log(this.deityService.deityData);
}
);

Camunda:How to import json file data to embeded form?

I have json file in which i pernamently rewrite data from my database ,so inside it i have several json object ( i mean i have json array inside my json File) i want to make one form for one json object for this reason i have used embedde forms i mean user task form and angular ui , here is my code:
v
ar jsonFile;
inject([ ‘$scope’, ‘$http’, ‘$location’, ‘Uri’, function($scope, $http, $location, Uri) {
camForm.on('form-loaded', function () {
$http.get(Uri.appUri("engine://engine/:engine/process-definition/key/my-process-key/startForm")).success(function(result){
var contextPath = result.contextPath + '/forms/';
var filePath = contextPath + 'data.json';
$.getJSON(filePath, function(json) {
jsonFile = json;
});
});
});
var jsonData1=JSON.stringify(jsonFile);
var rawData=JSON.parse(jsonData1);
var documentData = $scope.documentData = {
"id":rawData[i]["id"],
"organizationNameGE":rawData[i]["organizationNameGE"],
"organizationNameEN":rawData[i]["organizationNameEN"],
"cardNumber":rawData[i]["cardNumber"]
};
camForm.on('form-loaded', function() {
camForm.variableManager.createVariable({
name: 'documentData',
type: 'json',
value: documentData
});
});
but it throws exception that i have Unexpected end of input, but when i replace file data with custom data it works perfectly , what am i missing here?
how can i manage to generate one form for each json data object at a time?
Also i have tried this:
I have added TaskListener in user task process in java it looks like this
public class FormListener implements TaskListener {
public void notify(DelegateTask arg0) {
long id = (Long) arg0.getVariable("id");
String organizationNameGE=(String) arg0.getVariable("organizationNameGE");
String organizationNameEN=(String) arg0.getVariable("organizationNameEM");
String cardNumber=(String) arg0.getVariable("cardNumber");
arg0.setVariable("id",id);
arg0.setVariable("organizationNameGE",organizationNameGE);
arg0.setVariable("organizationNameEN",organizationNameEN);
arg0.setVariable("cardNumber",cardNumber);
}
}
and i also have this code inside my embeded form script:
inject(['$scope', '$http', function($scope, $http) {
var variableManager = camForm.variableManager;
// OnFormLoaded
camForm.on('form-loaded', function() {
// Fetch Variables
// - General
variableManager.fetchVariable('processInitiator'); // set by the engine
// - Process
variableManager.fetchVariable('id'); // set in an earlier form
variableManager.fetchVariable('organizationNameGE');
variableManager.fetchVariable('organizationNameEN');
variableManager.fetchVariable('cardNumber');
});
// OnVariablesFetched
camForm.on('variables-fetched', function() {
// After the variables are fetched, bind the value to the angular scope
// - General
$scope.processInitiator = variableManager.variable('processInitiator').value;
// - Process
$scope.id = variableManager.variable('id').value;
$scope.organizationNameGE= variableManager.variable('organizationNameGE').value;
$scope.organizationNameEN = variableManager.variable('organizationNameEN').value;
$scope.cardNumber=variableManager.variable('cardNumber').value;
});
but it doens;t gives me any result i mean it trows exception like this
SPIN/JACKSON-JSON-01004 Unable to find 'id'
what should i change to make my code work?
Just create a execution listner which executed at start of the user task, you can make it in the diagram. In the Listner implementation read the JSON as key value pair , set the key as camunda variable name and value as well. Now in the form give cam variable as the key that you have given in Listner implementation. You can implement the Listner in JavaScript /Java.

Sending data to parse.com and update angular $scope

I am sending data to a Class at parse.com, I would like to run this function and update the $scope without having to reload the view.
To create a Programme running the function below works fine, however it sometimes does not update the view following creating a new programme and it requires a page refresh (when the whole function is called as seen at the bottom - getProgrammes();
getProgrammes = function() {
$ionicLoading.show();
var programmesArray = [];
var QueryProgramme = Parse.Object.extend("Programme");
var query = new Parse.Query(QueryProgramme);
query.equalTo("userId", userId);
query.find({
success: function(results) {
for(var i=0; i < results.length; i++) {
var object = results[i];
var programmeData = { title : object.get('programmeTitle'),
id : object.id,
exercises : object.get('exerciseData')
};
programmesArray.push(programmeData);
}
$scope.programmes = programmesArray;
$scope.$apply();
$ionicLoading.hide();
},
error: function(error) {
alert('You do not have any Programmes - please create one');
}
})
};
getProgrammes();
I think I may be hacking this by using $scope.apply() - therefore making it unreliable. Assistance on the correct function to use in order to automatically update $scope would be great.
I've been using a library found here:
https://github.com/brandid/parse-angular-patch
Essentially I just reference the parse-angular.js file, and then include the dependency in my app, e.g.:
angular.module('app', [
'parse-angular',
]);
Then I just use Parse queries anytime I like and they participate correctly with $scope and $apply. The library just does some simple wrapping on the Parse methods to make the async calls obey the rules of angular.

AngularJS - updating the model shared by different controllers

I'm just starting with AngularJS, building my first test web app.
I have several controllers that share the same model.
This is my model:
uxctModule.factory ("ModelData", function () {
var data = {
param1: '',
param2: '',
param3: '',
[more params....]
}
return data
});
So this is an example of my controller
uxctModule.controller ('PageOne', function ($scope, ModelData){
$scope.data = ModelData;
[do things here]
});
I'm now trying to change the model by loading a string from a file, and I was expecting the app to update accordingly.
So in a controller I'm loading a file and trying to update the model:
uxctModule.controller ('NavigationController', function ($scope, ModelData) {
$scope.data = ModelData;
$scope.browsePressed = function (evt) {
var f = evt.target.files[0];
if (f) {
var r = new FileReader();
r.onload = function(e) {
var contents = e.target.result;
console.log (contents);
console.log ("ModelData was " + ModelData.param1);
ModelData = JSON.parse(contents);
console.log ("ModelData is now " + ModelData.param1);
}
r.readAsText(f);
}
else {
alert("Failed to load file");
}
}
});
I've built a "debugger" div in the html to see the model:
<div id="debuggerBox" ng-controller="Debugger" width='300'>
<pre>{{data | json}}</pre>
</div>
...whose controller is simply:
uxctModule.controller ('Debugger', function ($scope, ModelData){
$scope.data = ModelData;
});
Now, when changing the model content loading the external file I can see on the console the right logs (values changed), but on the debugger box the Model object is still holding the old values.
As I said, I'm an AngularJS beginner, so maybe I'm doing something really wrong here. Any help is appreciated :)
The problem is you're replacing the whole object:
ModelData = JSON.parse(contents);
with this, the ModelData references another object but the original object is not modified.
You could fix this by copying field by field to the ModelData. Sample code:
var tempModelData = JSON.parse(contents);
ModelData.param1 = tempModelData.param1;
or you could try angular.copy:
angular.copy(JSON.parse(contents), ModelData);
Also try $scope.$apply to let angular aware of the changes:
$scope.$apply(function(){
angular.copy(JSON.parse(contents), ModelData);
});

Categories