如何从单独的控制器设置Angular范围变量

时间:2016-05-31 20:00:34

标签: angularjs

我正在使用Angular作为嵌入式系统的UI。我有应用程序设置,以便您可以在桌面浏览器中运行UI(嵌入式系统的模拟)。我有一个服务层,其中包含嵌入式系统的所有API函数。因此,对于模拟,我只需更换服务层来模拟API函数。这很好用,但现在我的问题是我需要在模拟中做一些不属于嵌入式系统的东西。

我不希望任何控制器中的模拟代码。我已成功地通过加载单个.js文件来获取模拟控制器,甚至可以在单独的控制器中调用函数,但我无法更改范围变量的值。它没有像我期望的那样起作用。

这是一个演示会发生什么的演示。我在第二个控制器的第一个控制器中调用一个函数并传递一个参数。控制台打印出正确的值,但范围变量不会改变。

var app = angular.module('myApp', [])

.controller('Ctrl_1', function( $scope )
{
  $scope.myFunction = function( myParam )
  {
    console.log('Ctrl_1: ' + myParam );

    // Demonstrates that the function is called, and with the correct value for myParam.
    $('.console').append('<li>' + myParam + '</li>');

    $scope.myVar = myParam;
  }

  $scope.myFunction('Foo');
});

// sim.js
$('.app-wrapper').attr('ng-controller', 'Ctrl_2');

app.controller('Ctrl_2', function( $scope, $controller, $timeout )
{
  var Ctrl_1_ViewModel = $scope.$new();

  $controller('Ctrl_1', { $scope: Ctrl_1_ViewModel } );

  //$timeout( function() { Ctrl_1_ViewModel.myFunction('Bar') } );

  $scope.testFunction = function()
  {
    Ctrl_1_ViewModel.myFunction('Bar');

    console.log('Ctrl_2: ' + Ctrl_1_ViewModel.myVar );
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="myApp" class="app-wrapper">
  <div ng-controller="Ctrl_1">
    <h3>myVar = '{{ myVar }}'</h3>
    <button ng-click="testFunction()">Set myVar equal to 'Bar'</button>
  </div>
  <ul class="console" style="list-style-type: none; padding: 0;"></ul>
</div>

我还有JSFiddle of the demo

我怎样才能让它发挥作用?或者,我应该考虑采用不同的方法吗?

2 个答案:

答案 0 :(得分:1)

整个方法完全错了。您如何期望angular知道您手动更改了ngController?您必须重新编译h3元素才能让角度知道此更改:

$compile($document.find('h3'))(Ctrl_1_ViewModel);

一个工作示例:https://jsfiddle.net/cL96m2zx/5/

并且在旁注 - 当你使用Angularjs时你不应该操纵控制器的dom,你需要停止DOM操作并使用angular指令中的build(或编写你自己的自定义指令并操纵它)从那里的DOM - 但作为最后的手段)。

答案 1 :(得分:0)

您可以创建一个管理数据的工厂,并使用watch更新第二个控制器。

或者也可以用事件。请查看docs。 根据您的活动方向,您需要$broadcast$emit。使用类似$rootScope.$broadcast('custom:eventName', {data: 'Bar'})的内容来通知$scope.$on('custom:eventName', function(evt, data) { ... }

等子范围内的任何侦听器

如果您想通知应用程序的许多部分有关更改,我会使用事件。如果您只有两个或三个不同的控制器来监视更改,那么对数据进行监视就可以了。

请查看下面的演示或此fiddle

&#13;
&#13;
var app = angular.module('myApp', [])
.factory('sharedData', SharedDataService)
.controller('Ctrl_1', function( $scope , sharedData)
{
	$scope.$watch(function() {
    	return sharedData.getVar('myVar');
    }, function(newVal) {
    	$scope.myFunction(newVal);
    })
	
    $scope.myFunction = function( myParam ) {
        console.log('Ctrl_1: ' + myParam );

        // Demonstrates that the function is called, and with the correct value for myParam.
        $('.console').append('<li>' + myParam + '</li>');

        $scope.myVar = myParam;
      }
  
  //$scope.myFunction('Foo');
});

// sim.js
$('.app-wrapper').attr('ng-controller', 'Ctrl_2');

app.controller('Ctrl_2', function( $scope, $controller, $timeout, sharedData)
{
	//var Ctrl_1_ViewModel = $scope.$new();
  
  //$controller('Ctrl_1', { $scope: Ctrl_1_ViewModel } );
  
  //$timeout( function() { Ctrl_1_ViewModel.myFunction('Bar') } );
  
  $scope.testFunction = function()
  {
  	//Ctrl_1_ViewModel.myFunction('Bar');
    sharedData.setVar('myVar', 'Bar');
    //console.log('Ctrl_2: ' + Ctrl_1_ViewModel.myVar );
  }
});

function SharedDataService() {
	var _privateData = {
    	myVar: 'Foo'
    };
    
	var factory = {
    	setVar: function(name, newVal) {
        	_privateData[name] = newVal;
        },
        getVar: function(name) {
        	return _privateData[name]
        }
    };
    
    return factory;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" class="app-wrapper">
  <div ng-controller="Ctrl_1">
    <h3>myVar = '{{ myVar }}'</h3>
    <button ng-click="testFunction()">Set myVar equal to 'Bar'</button>
  </div>
  <ul class="console" style="list-style-type: none; padding: 0;"></ul>
</div>
&#13;
&#13;
&#13;