I try to update my chart when data is pushed to a websocket. I want to do this by defining my own directive in angular, but the binding of data does not work. The Code:
angular.directive("myChart", ['service', function (service) {
function ChartController ($scope) {
var ws = new WebSocket("url/to/websocket/");
var data = service.initData(); // initialize data table
ws.onmessage = function (event) { // listen and update data
data = service.updateData(event.data);
$scope.recentData = data;
}
$scope.recentData = data;
}
function link(scope, element, attr) {
function drawChart (data) {}
scope.$watch('data', function (newD, old) {
drawChart(newD);
}, true);
}
return {link: link, controller: ['$scope', ChartController], restrict: 'EA'}
}
Thats a simplistic example, of what i want to do. The service and data changes work well, i can log the current values. However drawChart() gets called only on startup and not on every mutation.
The Controller has to be part of the directive and not wrapped around
You need to notify angular of the changes by using a method that calls apply() after the change occurs, which is preferably done by using $timeout.
angular.directive("myChart", ['service', '$timeout', function (service, $timeout) {
function ChartController ($scope) {
var ws = new WebSocket("url/to/websocket/");
var data = service.initData(); // initialize data table
ws.onmessage = function (event) { // listen and update data
data = service.updateData(event.data);
$scope.recentData = data;
}
$scope.recentData = data;
}
function link(scope, element, attr) {
function drawChart (data) {}
scope.$watch('data', function (newD, old) {
$timeout(function(){
drawChart(newD);
});
}, true);
}
return {link: link, controller: ['$scope', ChartController], restrict: 'EA'}
}
Related
I'm building a chrome app and I use Vue.js for the options page.
So I want to load settings from the chrome storage and put it into the vue data.
My problem is, that i can not access the vue compontens from inside the chrome storage callback. Every time i call it inside the callback, all vue elements are undefined.
Is there a way, to let the chrome storage cb function return a value, or give it an extra callback.
Here is my code
name: 'app',
data: function () {
return {
data []
}
},
methods: {
init: function() {
chrome.storage.sync.get('series', function (storageData) {
this.data = storageData //this is not possible, because this.data is undefined
})
});
}
},
created: function () {
this.init();
}
}
If using ES6 and transpiling (preferred approach). Note: arrow functions don't create a new context.
init: function() {
chrome.storage.sync.get('series', storageData => {
this.data = storageData
});
}
ES5 workaround:
init: function() {
var self = this;
chrome.storage.sync.get('series', function (storageData) {
self.data = storageData
});
}
I have declare function to get WCF Rest the name is service.js, the url get Json data. Then I create another function to get data entryCtrl.js then show to html
service.js
(function (app) {
app.service("CRUD_AngularJs_RESTService", function ($http) {
this.getAllEntry = function () {
return $http.get("http://localhost:51458/ServiceRequest.svc/GetAllRequest/");
};
});
})(angular.module('model'));
entryCtrl.js
(function (app) {
'use strict';
app.controller('entryCtrl', entryCtrl);
entryCtrl.$inject = ['$scope'];
function entryCtrl($scope) {
$scope.pageClass = 'page-entry';
$scope.GetAllRecords = function() {
var promiseGet = CRUD_AngularJs_RESTService.getAllEntry();
promiseGet.then(function (pl) { $scope.EntryData = pl.data },
function (errorPl) {
$log.error('Some Error in Getting Records.', errorPl);
});
}
}
})(angular.module('model'));
view entry.html
<table data-ng-controller="entryCtrl">
<tbody data-ng-repeat="entry in EntryData">
<tr>
<td>{{entry.name}}</td>
<td>{{entry.telpon}}</td>
<td>{{entry.foobar}}</td>
</tr>
</tbody>
</table>
I don't have any error, my data in table not show anything. What must I try to know the function it's work or not?
jush have warning XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. I don't know what it is mean.
The function GetAllRecords() is not set to the $scope. You need to set $scope.GetAllRecords = GetAllRecords before the call to $scope.GetAllRecords():
function entryCtrl($scope) {
$scope.pageClass = 'page-entry';
$scope.GetAllRecords = function() {
var promiseGet = CRUD_AngularJs_RESTService.getAllEntry();
promiseGet.then(function (pl) { $scope.EntryData = pl.data },
function (errorPl) {
$log.error('Some Error in Getting Records.', errorPl);
});
}
$scope.GetAllRecords();
}
Alternatively, you can simply call GetAllRecords() directly, since you don't seem to need it in the $scope:
function entryCtrl($scope) {
$scope.pageClass = 'page-entry';
(function() {
var promiseGet = CRUD_AngularJs_RESTService.getAllEntry();
promiseGet.then(function (pl) { $scope.EntryData = pl.data },
function (errorPl) {
$log.error('Some Error in Getting Records.', errorPl);
});
})();
}
I'm new to this so sorry if I'm asking something obvious. I have an app with controller holding some config variables in scope. I have a custom directive used inside ng-repeat that will have to make use of this config. For debugging purposes I need the changes to config bee reflected inside the directive. How can I achieve this.What I have so far is not working my pointsmap is undefined
angular.module('demo', [])
.directive('demoDir', function () {
var dirController = ['$scope', function ($scope) {
$scope.totalPoints = 0;
$scope.$watch('person', function(newVal, oldVal){
resetPoints(newVal);
}, true);
function resetPoints(pPerson){
$scope.totalPoints = $pointsMap['VIP'] * pPerson.points ;
}
return {
restrict: 'E',
scope: {
person: '=' ,
pointsMap : '='
},
controller: dirController,
template: '<span> {{totalPoints}}</span>'
}
})
.controller('mainAppController', function ($compile, $scope, $q ) {
/*CONFIG */
$scope.points = {
'VIP': 8.50,
'Standard': 7.50,
};
});
<demoDir person='myobject' pointsMap='points' />
Any particular reason why you want your directive to have isolated scope? If there is no restriction to use isolated scope, you can simply make the scope of the directive as false(now directive will use parent scope)
angular.module('demo', [])
.directive('demoDir', function () {
var dirController = ['$scope', function ($scope) {
$scope.totalPoints = 0;
$scope.$watch('person', function(newVal, oldVal){
resetPoints(newVal);
}, true);
function resetPoints(pPerson){
$scope.totalPoints = $pointsMap['VIP'] * pPerson.points ;
}
return {
restrict: 'E',
scope: false,
controller: dirController,
link: function(scope, element, attrs){
//scope.points should be available
}
template: '<span> {{totalPoints}}</span>'
}
})
.controller('mainAppController', function ($compile, $scope, $q ) {
/*CONFIG */
$scope.points = {
'VIP': 8.50,
'Standard': 7.50,
};
});
//assuming that your directive is housed inside the mainAppController
<div ng-controller="mainAppController">
<demoDir/>
</div>
You will also have access to the parent scope properties in the directive's link function if you want to use.
Having trouble loading an external json file and having it's contents display on my view. I've included my view, controller and services code. What do I need to change?
view.html
<div ng-controller='BaseCtrl'>
<table class="table table-hover">
<tbody>
<tr class="tr-sep" ng-repeat="example in examples" ng-click="showUser(example)">
<td>{{example.name}}</td>
<td>{{example.type}}</td>
<td>{{example.size}}</td>
</tr>
</tbody>
</table>
</div>
controller.js
'use strict';
angular.module('projyApp')
.controller('BaseCtrl', function ($scope, data) {
$scope.examples = data.getAllExamples();
$scope.showUser = function(example) {
window.location = '#/user/' +example.size;
};
});
service.js
'use strict';
angular.module('projyApp')
.service('data', function data() {
var examples;
var getAllExamples = function () {
$http.get("../../TestData/Examples.json").success($scope.examples = data.examples);
};
});
Your service code isn't correct. I see the following problems:
You're creating a local variable getAllExamples that's not accessible from outside the service;
You're using the $http service, but that dependency isn't expressed in the service constructor;
You're trying to update the scope from the service, but it's inaccessible from there. Plus, the $scope variable is not even defined inside the service code.
Here's how your service could look like:
.service('data', function($http) {
this.getAllExamples = function(callback) {
$http.get("../../TestData/Examples.json")
.success(function(data) {
if (callback) callback(data.examples);
});
};
});
And your controller code would be like this:
.controller('BaseCtrl', function ($scope, data) {
data.getAllExamples(function(examples) {
$scope.examples = examples;
});
$scope.showUser = function(example) {
window.location = '#/user/' +example.size;
};
});
You could ditch the callback in the getAllExamples function and work directly with the $http.getreturned promise, but that's a bit more complicated.
Update Added a Plunker script to illustrate the code above.
Main module definition should look like:
angular.module("projyApp",[/*dependencies go here*/]);
Service should look like
//this use of module function retrieves the module
//Note from comments in angular doc: This documentation should warn that "angular.module('myModule', [])" always creates a new module, but "angular.module('myModule')" always retrieves an existing reference.)
angular.module('projyApp')
.service('dataService', [/*dependencies,*/function() {
var service = {
examples:[],
getAllExamples = function () {
$http.get("../../TestData/Examples.json").success(function(returnedData){examples = returnedData});
}
}
return service;
});
Controller should look like:
angular.module('projyApp')
.controller('BaseCtrl', function ($scope, dataService) {
$scope.examples = [];
$scope.showUser = function(example) {
window.location = '#/user/' +example.size;
};
$scope.$watch(function(){return dataService.examples}, function(newVal,oldVal) {$scope.examples = newVal});
});
Also you can add
debugger;
on an line to trigger Chrome to break (like a breakpoint but without having to dig through the scripts at run-time) so long as the Debugging Panel is open (F12)
You should use a callback instead of assigning in to a scope in you data service. By doing that, you can use this function in multiple controllers an assign values to appropriate scopes.
Data Service
var getAllExamples = function (callback) {
$http.get("../../TestData/Examples.json").success(function(data) {
if (typeof callback === "function") callback(data);
});
};
Controller
data.getAllExemples(function(data) {
$scope.examples = data;
});
EDIT
Another what is to create a promise object.
Data Service
var getAllExamples = function () {
return $http.get("../../TestData/Examples.json");
};
Controller
var promise = data.getAllExemples();
promise.then(function(data) {
$scope.examples = data;
});
EDIT 2
In your service, you need to return your functions
angular.module('projyApp')
.service('data', function data() {
var examples;
return {
getAllExamples: function () {
$http.get("../../TestData/Examples.json").success(...);
}
};
});
I have a strange thing:
my controller works, but getHash service is called on loading, instead on calling saveit() function on index html:
angular.module('myApp.controllers', [])
.controller('MyCtrl', ['$scope','$http','getHash', function ($scope,$http, getHash) {
$scope.keys = getHash.get(function(keys) {
$scope.key = keys.key;
});
$scope.saveit = function () {
$scope.formData = {
'key' : $scope.key
};
console.log ($scope.formData);
//Do Something with formData
}
}
This Example is not working, the $scope.key is empty, but the getHash Service is called as it should.
angular.module('myApp.controllers', [])
.controller('MyCtrl', ['$scope','$http','getHash', function ($scope,$http, getHash) {
$scope.saveit = function () {
$scope.keys = getHash.get(function(keys) {
$scope.key = keys.key;
});
$scope.formData = {
'key' : $scope.key
};
console.log ($scope.formData);
//Do Something with formData
}
}
Has anyone an explanation for this behavior? how can i get $scope in the function saveit?
or save variables to $scope inside saveit?
Thanks, Patrick