I'm learning AngularJS and I have one JSON file with data that I want to load into separate variables.
My JSON file has two objects/arrays: "views" and "addressbook". I can bind the data to a $scope.variabale in the html but but that's not what i'm looking for. I would like to load the views and addressbook into a "var views" and a "var adressbook" so i can access them with jquery.
My JSON:
{
"myData": {
"views": [
{
"view": "Nieuwe activiteit",
"link": "index.html",
"active": true
},
{
"view": "Activiteiten",
"link": "activiteiten.html",
"active": false
}
],"adresboek": [
{
"Voornaam": "Ruben",
"e-mail": "ruben#e-mail.com",
"mobiel": "0612345678",
"hasFacebook": true,
"hasTwitter": true
},
{
"Voornaam": "Roos",
"e-mail": "roos#e-mail.com",
"mobiel": "0612345677",
"hasFacebook": true,
"hasTwitter": true
}
]
}
}
What i'm trying to get:
var alldata = $http.get('data/data.json').then(function(res) {
var views = res.data.mydata.views;
var adresbook = res.data.mydata.adresbook;
});
I would like to bind the data like so:
$scope.views = alldata.views;
$scope.contacts = alldata.addressbook;
Any help is appreciated :)
Why exactly do you want to put these variables on the global scope/window? This is typically advised against. You may consider creating an Angular Service. A Service allows you to access variables across different modules.
In the context of your code, where is this $http.get request occurring?
EDIT: In response to your comment:
Ok, try something like this?
myApp.controller( 'getData', function($http){
this.onLoad: function(){
$http.get('data/data.json').then(function(res) {
$scope.views = allData.views;
$scope.contacts = allData.addressBook;
}
};
this.onLoad();
};
When you're first instantiating your angular controller it will call the loadData function and set your $scope variables.
(I didn't check your $http code, I just copied what you had down).
You can access the JavaScript global scope at any point by referencing the window object. Make sure to use $apply in angular if you modify data outside off the angular digest. In your example:
var alldata = $http.get('data/data.json').then(function(res) {
window.alldata = {
"views": res.data.mydata.views,
"addressbook": res.data.mydata.adresbook
};
});
You may now access the data in jQuery, e.g.:
console.log( window.alldata.views );
Related
I am loading a JSON that is almost 19,000 lines...minified to a single line its about 240k. I am loading it into my app via index.html file as a global var:
<script type="text/javascript" src="js/cdjson.js"></script>
var _countries = {
"country": {
"USA": {
"currency": {
"currencyCode":["USD"],
"currencyName":["United States Dollar"],
"currencySymbol":["$"]
},
"info": {
...
...
},
"phone" : {
...
},
"postal" : {
...
}
},
"CAN" : {
...
}
}
}
In the the controller its being assigned to a $scope variable $scope.countries = _countries.country ;. However, when the html DOM for that controller loads its trying to access the $scope variable before before the object is fully loaded into the $scope causing JS object errors like Cannot read property 'country' of undefined.
How can I prevent the page from rendering until the $scope object is fully loaded? The $scope country object is being used in a <select ng-repeat="countries as country">
Ideally your js files should be loaded at the end of your HTML so you dont have this problem. But if that is not an option for you then add this in your controller
$scope.countries = []
angular.element(document).ready(function () {
$scope.countries = _countries.country;
});
and in your HTML
<select ng-if="countries.length" ng-repeat="countries as country">
Have a flag that indicates when the data was fully loaded to the controller.
Something like
<select ng-if="countries.length" ng-repeat="countries as country">
I can fake getting data from json file with using $http but with $resource/ $httpBackend I don't get any results
$http.get (works)
$http.get('api/devices.json')
.then(function (result) {
...//
Above works just fine but the $httpBackend will work with json inline , but not pointing at JSON file
Controller file which calls the deviceResourceMock module
deviceResource.query(function(data) {
vm.devices = data;
});
deviceResourceMock module
app.run(function ($httpBackend) {
var devices = 'test.json'; // Put new json file in same directory
// ABOVE DOES NOT WORK
This DOES work below though
var devices = {"Devices": [
{
"DeviceId": 1,
"DeviceStatus": "Leaf Rake",
"id": "GDN-0011",
"ha": "Leaf rake with 48-inch wooden handle.",
"Urt": "blah"
}
]};
URL and WhenGet
var deviceUrl = "/api/devices";
$httpBackend.whenGET(deviceUrl).respond(devices.Devices);
Thoughts on why it doesn't work?
Is "devices.Devices" function?
I think code should be like
$httpBackend.whenGET(deviceUrl).respond(function(method,url,data) {
return devices.Devices;
});
I have a JSON object that looks like:
[
{
"empName": "John",
"ID": 1
},
{
"empName": "Sam",
"ID": 2
},
{
"empName": "Ben",
"ID": 3
}
]
In the view I want a dropdown where the user selects one of the names. I'm using ng-options to achieve this:
<select ng-options="item as item.empName for item in employees track by item.ID" ng-model="emp.selected">
</select>
If I hard-code the JSON into the variable employees in my controller the select renders. However if I use:
$.getJSON("path to JSON file",function(json){
$scope.employees = json;
});
The select is not populated. I've tried adding in $scope.$apply() to no avail. Any suggestions?
Update 1
Taking on board the answer from Iso I'm still left with the select not binding. For example If my javascript is:
app.controller('Ctrl', ['$scope', '$http', function($scope, $http) {
$scope.employees = [
{
"empName": "John",
"ID": 1
},
];
$http.get(" --PATH TO JSON-- ").then(function (res) {
$scope.employees = res.data;
console.log($scope.employees);
});
}]);
The select is still only populated with the first name 'John' despite the fact that the console.log returns the full object with all three names.
You need to either call $scope.$evalAsync(), or use $http instead of jQuery here (which I would recommend):
$http.get("path to JSON file").then(function (res) {
$scope.employees = res.data;
});
The reason for this is that $http is aware of AngularJS' digest cycle, whereas jQuery is not.
Refrain from using $scope.$apply() (which can fail if a digest cycle is in progress), and $timeout (which is heavy since it provokes a digest cycle of all your scopes).
Wrap your code inside $timeout:
$.getJSON("path to JSON file", function (json) {
$timeout(function () {
$scope.employees = json;
})
});
The call to $apply may fail when the digest cycle is already in progress.
But consider using the $http instead of using jQuery to pull data.
You should use promises with the $q library in Angular.
var getEmployees = function () {
var deferred = $q.defer();
$.getJSON("path to JSON file", function (json) {
deferred.resolve(json);
});
return deferred.promise;
}
getEmployees().then(res){
$scope.employees = res.data;
}
EDIT
If you use $timeout is not really as correct a solution, as it doesn't give you control over the synchronicity. However, using $http to make your calls comes with promises built in, I believe.
Recently I started getting familiar with meteor platform, and I stumbled on dilemma:
Is there a way to pass variables to Template.rendered, Template.created callbacks.
Let's say I have route
Router.route('/profile/:_id', {
name: 'profile'
});
and I want to somehow to pass that _id variable to Template.rendered callback:
Template.profile.rendered = function () {
//how can I get "_id" in here?
};
Is this possible? If so how can I do it?
Usually when you declare a route, you also specify a data context to provide to the template that will be rendered :
Router.route('/profile/:_id', {
name: 'profile',
data: function(){
return Meteor.users.findOne(this.params._id);
}
});
This way you can reference the user _id coming from the current data context assigned to the profile template like this :
Template.profile.rendered = function () {
console.log(this.data._id);
};
My application has been growing for the last year or so and I have finally started to split out common components by extending existing ones. I've found this to be really helpful - increasing speed of development and maintenance. My problem is that I haven't grasped the concept of using custom parameters on my components and was hoping that someone could offer some assistance in the following example. Specifically I don't seem to be able to access the custom parameter (myCustomParam) inside the proxy declared in the initComponent function:
MyEmployeeGrid = Ext.extend(Ext.grid.GridPanel, {
myCustomParam: "CompanyX",
initComponent:function() {
//Store Reader
var myReader = new Ext.data.JsonReader({
root : 'objectsToConvertToRecords',
idProperty: 'id',
fields : [
{name: 'id'},
{name: 'employee', allowBlank:false},
{name: 'department', allowBlank:false}
]
});
//Store Proxy
var dwrProxy = new Ext.ux.data.DwrProxy({
apiActionToHandlerMap : {
read : {
dwrFunction : EmployeeService.readCompanyEmployees,
getDwrArgsFunction: function(request, recordDataArray, oldRecordDataArray) {
return [myCustomParam];
}
}
}
});
//Setup Params for the grid
Ext.apply(this, {
store: new Ext.data.Store({
proxy: dwrProxy,
reader: myReader,
autoLoad : true,
autoSave: true
}),
columns: [{header: "Employee", dataIndex: 'employee'},
{header: "Department", dataIndex: 'department'}]
});
MyEmployeeGrid.superclass.initComponent.apply(this, arguments);
} // eo function initComponent
,onRender:function() {
MyEmployeeGrid.superclass.onRender.apply(this, arguments);
} // eo function onRender
});
Ext.reg('myemployeegrid', MyEmployeeGrid);
myCustomParam is a property of the object in question. It is never declared as a variable in its own right. You can see this by running the code through jslint.
You want this.myCustomParam.
If you're trying to pass in parameters, however, you might want to try this way instead:
MyGrid = Ext.extend(Ext.grid.GridPanel, {
constructor: function(cfg) {
cfg = cfg || {};
// ... do stuff ...
MyGrid.superclass.constructor.call(this, cfg);
}
});
I have a strong feeling this is to do with scope around the point at which getDwrArgsFunction is called. It possibly doesn't know what myCustomParam is (despite the fact this should possibly be this.myCustomParam, and that you'd want to set this after you'd applied any config) because it's not declared in the DwrProxy object and has no reference back to its owning MyEmployeeGrid object.
I'd debug/attempt to fix in the following way:
Rename myCustomParam to
this.myCustomParam and test
Set scope and test
Create getDwrArgsFunction using
createDelegate
(http://dev.sencha.com/deploy/dev/docs/source/Function.html#method-Ext.util.Functions-createDelegate)
and test
DISCLAIMER: Some of those will be no good depending on your DwrProxy etc (which we can't see the code for)
The proxy cannot access the variable because it is not defined in the scope of the proxy itself. I have been struggling with things like this in the past, I thought that components would act like closures and keep track of the variable, but they dont.
You can solve your problem by handing the scope of the grid to the handler function explicitly by making it a delegate, what you do have to change for that is making the variable you would like to access an instance variable instead of just a local variable.
Changes:
MyEmployeeGrid = Ext.extend(Ext.grid.GridPanel, {
myCustomParam: "defaultValue",
initComponent:function() {
...
//Store Proxy
var dwrProxy = new Ext.ux.data.DwrProxy({
apiActionToHandlerMap : {
read : {
dwrFunction : EmployeeService.readCompanyEmployees,
getDwrArgsFunction: function(request, recordDataArray, oldRecordDataArray) {
return [this.myCustomParam];
}.createDelegate(this)
}
}
});
var myGridInstance = new MyEmployeeGrid({ myCustomParam: 'ValueForThisInstance' });
Hope this helps you, good luck