You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular中跨控制器共享数据以更新Chart.js图表?

How to Share Data Between Angular Controllers for Chart.js

Hey there! Let's work through how to share your fetched sensor data between myCtrl and LineCtrl in Angular. The key issue here is that each controller has its own isolated $scope, so you can’t just push data directly from one to the other. Let’s go over the best solutions for this.

Angular services are singleton objects, which makes them perfect for sharing data across controllers. This keeps your code decoupled and follows Angular's best practices.

Step 1: Create a Data Sharing Service

First, define a service to store and retrieve your sensor data. Make sure to define your module only once (avoid redefining it in multiple files!).

// Define your module once in one of your files
var app = angular.module('statisticsApp', ['chart.js']);

// Create a singleton service for shared sensor data
app.service('SensorDataService', function() {
    var storedData = {};

    return {
        // Temperature data handlers
        setTemperature: function(data) {
            storedData.temperature = data;
        },
        getTemperature: function() {
            return storedData.temperature;
        },
        // pH data handlers
        setPh: function(data) {
            storedData.ph = data;
        },
        getPh: function() {
            return storedData.ph;
        },
        // Humidity data handlers
        setHumidity: function(data) {
            storedData.humidity = data;
        },
        getHumidity: function() {
            return storedData.humidity;
        }
    };
});

Step 2: Update myCtrl to Store Data in the Service

Modify your Data_Controller.js to inject the service, fix data type issues (you were pushing arrays instead of numbers), and save parsed data after the API call.

// Retrieve the existing module (don't redefine it!)
var app = angular.module('statisticsApp');

app.controller('myCtrl', function ($scope, $http, SensorDataService) {
    "use strict";
    
    $http({
        method : "POST",
        url : "GatewayAPI.php",
    }).then(function mySuccess(response) {
        $scope.records = response.data;
        var chartResultTemp = [];
        var chartResultph = [];
        var chartResultHum = [];

        for(var i=0; i<72; i++) {
            var mydata = $scope.records.data[i];
            var resultType = mydata.data.substring(3, 4);
            // Convert string value to number for Chart.js compatibility
            var sensorValue = parseFloat(mydata.data.substring(6,9));

            switch(resultType) {
                case "A":
                    chartResultTemp.push(sensorValue);
                    break;
                case "B":
                    chartResultph.push(sensorValue);
                    break;
                default:
                    chartResultHum.push(sensorValue);
            }
        }

        // Save parsed data to the shared service
        SensorDataService.setTemperature(chartResultTemp);
        SensorDataService.setPh(chartResultph);
        SensorDataService.setHumidity(chartResultHum);

        // Keep your test variables if needed for debugging
        $scope.test2 = chartResultTemp;
        $scope.test4 = chartResultph;
        $scope.test5 = chartResultHum;
    });
});

Step 3: Update LineCtrl to Fetch Data from the Service

Since your API call is asynchronous, use $watch to detect when the data is ready in the service. Note that your fetched data has 72 entries but your chart only has 12 labels—you’ll need to process the data (e.g., average every 6 entries) to match the label count.

// Retrieve the existing module
var app = angular.module('statisticsApp');

app.controller("LineCtrl", function ($scope, SensorDataService) {
    "use strict";
    $scope.labels = ["0200", "0400", "0600", "0800", "1000", "1200", "1400", "1600", "1800", "2000", "2200", "0000"];
    $scope.series = ['Temperature (℃)'];
    
    // Initialize with mock data as fallback
    $scope.data = [
        [26.5, 26.8, 26.3, 25.8, 29.4, 30.2, 31.5, 31.0, 28.4, 27.6, 26.3, 25.7]
    ];

    // Watch for changes in the shared temperature data
    $scope.$watch(
        function() { return SensorDataService.getTemperature(); },
        function(newTempData) {
            if(newTempData && newTempData.length > 0) {
                // Example: Downsample 72 entries to 12 by averaging every 6 values
                var processedData = [];
                for(var i=0; i<newTempData.length; i+=6) {
                    var chunk = newTempData.slice(i, i+6);
                    var average = chunk.reduce((sum, val) => sum + val, 0) / chunk.length;
                    processedData.push(average.toFixed(1)); // Round to 1 decimal place
                }
                $scope.data[0] = processedData;
            }
        }
    );

    $scope.onClick = function (points, evt) {
        console.log(points, evt);
    };
});

If you need a quick fix (though it’s not ideal for large apps due to global scope pollution), you can use $rootScope:

  1. Inject $rootScope into myCtrl and save data there:
    $rootScope.chartResultTemp = chartResultTemp;
    
  2. Watch for changes in LineCtrl:
    $scope.$watch('$root.chartResultTemp', function(newData) {
        if(newData) {
            $scope.data[0] = newData;
        }
    });
    

Key Fixes for Your Original Code

  • Avoid redefining the module: In your original code, you redefined angular.module('statisticsApp', ['chart.js']) in both files, which resets the module. Only define it once, then retrieve it with angular.module('statisticsApp') in other files.
  • Data type conversion: Your original code pushed arrays (e.g., [mydata.data.substring(6,9)]) into result arrays. Use parseFloat() to convert these strings to numbers so Chart.js can render them correctly.
  • Data length matching: Your fetched data has 72 entries, but your chart labels only have 12. Process the data (average, downsample) to match the label count for proper rendering.

内容的提问来源于stack exchange,提问作者Daine MacTavish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:26:15