Please spare me if this is a beginner type of question. I'm playing Highcharts.js with Angular.js, but it's seems like directive scope is not binding to value. Below are my codes.
HTML - but it's working inside this expressions {{xaxis}} {{seriesdata}}
<div class="container" ng-controller='chartController'>
<div class="row">
<div class="col-md-6">
<line-chart xaxis='xaxis' seriesdata='seriesdata'></line-chart>
{{xaxis}}
{{seriesdata}}
</div>
<div class="col-md-6">
<bar-chart options='pieOptions'></bar-chart>
</div>
</div>
</div>
directive.js
(function() {
'use strict';
angular
.module('chart')
.directive('lineChart', lineChartDirective);
/* #ngInject */
function lineChartDirective() {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
scope: {
xaxis: '=xaxis',
seriesdata: '=seriesdata'
},
link: function(scope, element) {
Highcharts.chart(element[0], {
chart: {
type: 'spline',
zoomType: 'x'
},
plotOptions: {
line: {
dataLabels: {
enabled: true
}
}
},
title: {
text: 'Profit Ratio by Month'
},
xAxis: {
categories: scope.xaxis
},
yAxis: {
title: {
text: 'Profit %'
}
},
series: [
{
name: 'Total',
data: scope.seriesdata
}
]
});
}
}
}
})();
service.js
(function() {
'use strict';
angular
.module('chart')
.factory('chartData', chartDataFactory);
chartDataFactory.$inject = ['$http'];
/* #ngInject */
function chartDataFactory($http) {
function getData() {
return $http.get('../../data/sampleData.json').then(function(result) {
return result.data;
})
}
return {
getData: getData
}
}
})();
controller.js
(function() {
'use strict';
angular
.module('chart')
.controller('chartController', chartController);
chartController.$inject = ['$scope', 'chartData', 'lodash'];
/* #ngInject */
function chartController($scope, chartData, lodash) {
var vm = this;
chartData.getData().then(function(data) {
$scope.chartData = data;
$scope.xaxis = data.SEO[0]["SEO-MOD-001"]["SEO-END-001"];
$scope.seriesdata = data.SEO[0]["SEO-MOD-001"]["SEO-END-002"];
console.log($scope.xaxis);
console.log($scope.seriesdata);
});
$scope.pieOptions = {
chart: {
type: 'column'
},
title: {
text: 'Projects'
},
xAxis: {
categories: ['Noreil', 'Ken', 'Alfie', 'Francis']
},
yAxis: {
title: {
text: 'Completed Projects'
}
},
series: [
{
name: 'Quarter 1',
data: [23, 11, 34, 26]
},
{
name: 'Quarter 2',
data: [14, 20, 26, 30]
}
]
}
}
})();
When the directive link function gets executed, you don't have data yet. So try following in link function:
var unwatch = scope.$watch('[xaxis, seriesdata]', function (results) {
if (results[0] && results[1]) {
init();
unwatch();
}
}, true);
function init() {
// Highcharts.chart(element[0], { ...
}
Related
I'm trying to write a directive for HighCharts in AngularJS which supports two way data binding. On click of a function in the HTML, am trying to load the graph with new data.
Please check the below snipet.
HTML:
<hc-area-chart data="areaData"></hc-area-chart>
<button ng-click="updateGraph()">Update function</button>
Controller:
angular.module('myModule', [])
.directive('hcAreaChart', function () {
return {
restrict: 'E',
template: '<div></div>',
scope: {
title: '#',
data: '='
},
link: function (scope, element) {
Highcharts.chart(element[0], {
chart: {
type: 'area'
},
title: {
text: null
},
xAxis: {
categories: ['Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun']
},
plotOptions: {
pointStart: 4,
},
series: [{
showInLegend: false,
data: scope.data
}]
});
}
};
})
.controller('myController', function ($scope) {
$scope.areaData = [0,6,5,7,5,4.5,10];
$scope.updateGraphData = function () {
console.log("inside update function");
$scope.areaData = [10,20,30,40,50,60,70];
}
});
I think you should try something like this
link: function (scope, element) {
scope.$watch('data', function(){
Highcharts.chart(element[0], {
chart: {
type: 'area'
},
title: {
text: null
},
xAxis: {
categories: ['Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun']
},
plotOptions: {
pointStart: 4,
},
series: [{
showInLegend: false,
data: scope.data
}]
});
})
}
Here is my angularjs code. I have created different routes but i am unable to resolve my contract.dashboard route. If i remove the route object, it works fine but when i tried to reslove something from my service, it dose not work.
(function() {
'use strict';
angular
.module('app.contracts')
.run(appRun);
var _base = {
// Contract Base Contractor
contract: {
controllerAs: 'c',
controller: ['$scope', '$state', 'ContractModel', function($scope, $state, ContractModel){
'ngInject';
var that = this;
$scope.$watch(function(){ return $state.current.data.mode; }, function() { that.mode = $state.current.data.mode; });
that.contract = new ContractModel();
}]
}
};
/* #ngInject */
function appRun(routerHelper) {
routerHelper.configureStates(getStates());
}
function getStates() {
return [
{
state: 'contract',
config: angular.extend({
abstract: true,
template: '<contract-manager><ui-view/></<contract-manager>',
url: '/contract'
}, _base.contract)
},
{
state: 'contract.new',
config: angular.extend({
url: '/new',
template: '<contract-editor mode="c.mode" contract="c.contract"></<contract-editor>',
title: 'Contract Editor',
data: {
mode: 'new'
}
}, _base.contract)
},
{
state: 'contract.dashboard',
config: angular.extend({
url: '',
template: '<contract-dashboard></contract-dashboard>',
title: 'Contract Dashboard',
data: {
mode:'dashboard'
},
resolve: {
stubs: function(stubs){
return stubs.service.registerGetCustomers();
}
}
}, _base.contract)
}
];
}
})();
I get the chart when I hard code the data. But when I get the data from a server I don't see the chart. I saw many questions on this but they didn't help me. I change the data object with the scope variable but I still don't get the data
This is what I've done:
angular.module('myModule', [])
// Directive for generic chart, pass in chart options
.directive('hcPieChart', function () {
return {
restrict: 'E',
template: '<div></div>',
scope: {
title: '#',
data: '='
},
link: function (scope, element) {
Highcharts.chart(element[0], {
chart: {
type: 'pie'
},
title: {
text: scope.title
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.percentage:.1f} %'
}
}
},
series: [{
data: scope.data
}]
});
}
};
})
.controller('myController', function ($scope,$http) {
$scope.GType = function(){
console.log("GType");
$http.get('http://192.168.1.100:5000/getPDAServiceAssignStatus')
.then(function (response) {
$scope.pieData = [];
console.log(JSON.stringify(response)+" Res");
for(i=0;i<response.data.length;i++){
$scope.pieData.push({
name: response.data[i].name,
y:response.data[i].y
});
}
console.log($scope.pieData);
});
}
$scope.GType();
// $scope.pieData = [{
// name: "Microsoft Internet Explorer",
// y: 56.33
// }, {
// name: "Chrome",
// y: 24.03,
// sliced: true,
// selected: true
// }, {
// name: "Firefox",
// y: 10.38
// }, {
// name: "Safari",
// y: 4.77
// }, {
// name: "Opera",
// y: 0.91
// }, {
// name: "Proprietary or Undetectable",
// y: 0.2
// }]
});
I need to bind an array of data to "data" part of highcharts which is embedded in
Angular directives but I don't know how exactly to do that.
This is my controller part which fetches data from repository:
vm.data = [];
function getVmAll(forceRefresh) {
return datacontext.esxservers.getAllWithoutPaging(forceRefresh, vm.vmAllSearchTemp)
.then(function (data) {
vm.data= data;
});
return data;
}
);
}
and here is the template which I use the controller in it:
<section class="mainbar" data-ng-controller="mbVirtualizationOverviewCtrl as vm">
<mb-virtualization-overview-donut-chart value="vm.data"></mb-virtualization-overview-donut-chart>
</section>
and the last but not least one is my directive which I use highcharts settings:
'use strict';
angular.module('app').directive('mbVirtualizationOverviewDonutChart', [
function () {
return {
restrict: "E",
templateUrl: '/app/directives/virtualizationOverview/mbVirtualizationOverviewDonutChartTemplate.html',
scope: {
value : "="
},
link: function (scope, el, attrs) {
scope.chart = Highcharts.chart(el[0], {
chart: {
type: 'pie',
},
title: {
text: scope.innerTitle
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: false
},
showInLegend: true
}
},
series: [{
data: undefined
}]
});
var init = true;
scope.$watch(
function () {
var chart = scope.chart;
if (init && scope.value.length > 0) {
init = false;
scope.value.forEach(function (item, index) {
chart.series[0].data.push(item);
});
}
});
}
};
}
]);
I'm experimenting with AngularJS. I want to show a basic Kendo Grid. I'm trying to do this using pure directives. With that in mind, I've looked at the Kendo UI / Angular JS project (https://github.com/kendo-labs/angular-kendo). Unfortunately, my
index.html:
<div>Products: {{products.length}}</div>
<div kendo-grid k-data-source="products" k-selectable="'row'"
k-pageable='{ "refresh": true, "pageSizes": true }'
k-columns='[
{ "field": "Name", "title": "Name"},
{ "field": "Department", "title": "Department"},
{ "field": "LastShipment", "title": "Last Shipment" }
]'>
</div>
controllers.js
function myController($scope) {
console.log("initializing controller...");
$scope.products = [
{ id:1, name:'Tennis Balls', department:'Sports', lastShipment:'10/01/2013' },
{ id:2, name:'Basket Balls', department:'Sports', lastShipment:'10/02/2013' },
{ id:3, name:'Oil', department:'Auto', lastShipment:'10/01/2013' },
{ id:4, name:'Filters', department:'Auto', lastShipment:'10/01/2013' },
{ id:5, name:'Dresser', department:'Home Furnishings', lastShipment:'10/01/2013' }
];
}
I've verified that I've wired up the controller properly. The activity count shows properly. However, the grid does not appear. I can't figure out what I'm doing incorrectly.
Thank you for your help.
You can also setup a Kendo DataSource as an AngularJS Service using the Factory method and inject this into your Controller to conform to AngularJS best practices and patterns.
Full source code and live demo: http://goo.gl/6Z9jop
Customer.cshtml
#{
ViewBag.Title = "Index";
}
<div>
<h2 ng-cloak>{{title}}</h2>
<div>
<div class="demo-section">
<div class="k-content" style="width: 100%">
<div kendo-grid="grid"
k-sortable="true"
k-pageable="true"
k-filterable="true"
k-editable="'inline'"
k-selectable="true"
k-columns='[
{ field: "CustomerID", title: "ID", width: "75px" },
{ field: "CompanyName", title: "Company"},
{ field: "ContactName", title: "Contact" },
{ field: "ContactTitle", title: "Title" },
{ field: "Address" },
{ field: "City" },
{ field: "PostalCode" },
{ field: "Country" },
{ field: "Phone" },
{ field: "Fax" }]'
>
</div>
<style scoped>
.toolbar { padding: 15px; float: right; }
</style>
</div>
</div>
<script type="text/x-kendo-template" id="toolbar">
<div>
<div class="toolbar">
<button kendo-button ng-click="edit(this)"><span class="k-icon k-i-tick"></span>Edit</button>
<button kendo-button ng-click="destroy(this)"><span class="k-icon k-i-tick"></span>Delete</button>
<button kendo-button ng-click="details(this)"><span class="k-icon k-i-tick"></span>Edit Details</button>
</div>
<div class="toolbar" style="display:none">
<button kendo-button ng-click="save(this)"><span class="k-icon k-i-tick"></span>Save</button>
<button kendo-button ng-click="cancel(this)"><span class="k-icon k-i-tick"></span>Cancel</button>
</div>
</div>
</script>
</div>
</div>
customerController.js
'use strict';
northwindApp.controller('customerController',
function ($scope, $rootScope, $location, customerDataSource)
{
customerDataSource.filter({}); // reset filter on dataSource everytime view is loaded
var onClick = function (event, delegate)
{
var grid = event.grid;
var selectedRow = grid.select();
var dataItem = grid.dataItem(selectedRow);
if (selectedRow.length > 0)
{
delegate(grid, selectedRow, dataItem);
}
else
{
alert("Please select a row.");
}
};
$scope.toolbarTemplate = kendo.template($("#toolbar").html());
$scope.save = function (e)
{
onClick(e, function (grid)
{
grid.saveRow();
$(".toolbar").toggle();
});
};
$scope.cancel = function (e)
{
onClick(e, function (grid)
{
grid.cancelRow();
$(".toolbar").toggle();
});
},
$scope.details = function (e)
{
onClick(e, function (grid, row, dataItem)
{
$location.url('/customer/edit/' + dataItem.CustomerID);
});
},
$scope.edit = function (e)
{
onClick(e, function (grid, row)
{
grid.editRow(row);
$(".toolbar").toggle();
});
},
$scope.destroy = function (e)
{
onClick(e, function (grid, row, dataItem)
{
grid.dataSource.remove(dataItem);
grid.dataSource.sync();
});
},
$scope.onChange = function (e)
{
var grid = e.sender;
$rootScope.lastSelectedDataItem = grid.dataItem(grid.select());
},
$scope.dataSource = customerDataSource;
$scope.onDataBound = function (e)
{
// check if there was a row that was selected
if ($rootScope.lastSelectedDataItem == null)
{
return;
}
var view = this.dataSource.view(); // get all the rows
for (var i = 0; i < view.length; i++)
{
// iterate through rows
if (view[i].CustomerID == $rootScope.lastSelectedDataItem.CustomerID)
{
// find row with the lastSelectedProductd
var grid = e.sender; // get the grid
grid.select(grid.table.find("tr[data-uid='" + view[i].uid + "']")); // set the selected row
break;
}
}
};
});
customerDataSource.js
'use strict';
northwindApp.factory('customerDataSource',
function (customerModel)
{
var crudServiceBaseUrl = "/odata/Customer";
return new kendo.data.DataSource({
type: "odata",
transport: {
read: {
async: false,
url: crudServiceBaseUrl,
dataType: "json"
},
update: {
url: function (data)
{
return crudServiceBaseUrl + "(" + data.CustomerID + ")";
},
type: "put",
dataType: "json"
},
destroy: {
url: function (data)
{
return crudServiceBaseUrl + "(" + data.CustomerID + ")";
},
dataType: "json"
}
},
batch: false,
serverPaging: true,
serverSorting: true,
serverFiltering: true,
pageSize: 10,
schema: {
data: function (data) { return data.value; },
total: function (data) { return data["odata.count"]; },
model: customerModel
},
error: function (e)
{
alert(e.xhr.responseText);
}
});
});
It looks as if the field names are spelled wrong. The following works for me:
<div kendo-grid k-data-source="products" k-selectable="'row'"
k-pageable='{ "pageSize": 2, "refresh": true, "pageSizes": true }'
k-columns='[
{ "field": "name", "title": "Name"},
{ "field": "department", "title": "Department"},
{ "field": "lastShipment", "title": "Last Shipment" }
]'>
</div>
Here is a live demo: http://jsbin.com/odeQAfI/2/edit
To avoid the NaN message in the pager you need to make the products field to be a Kendo DataSource:
function MyController($scope) {
$scope.products = new kendo.data.DataSource({
data: [
{ id:1, name:'Tennis Balls', department:'Sports', lastShipment:'10/01/2013' },
{ id:2, name:'Basket Balls', department:'Sports', lastShipment:'10/02/2013' },
{ id:3, name:'Oil', department:'Auto', lastShipment:'10/01/2013' },
{ id:4, name:'Filters', department:'Auto', lastShipment:'10/01/2013' },
{ id:5, name:'Dresser', department:'Home Furnishings', lastShipment:'10/01/2013' }
],
pageSize: 2
});
}
Here is a live demo: http://jsbin.com/ODElUfO/2/edit