我有一个带有范围变量
var1
的控制器和一个带有范围变量var2
的指令。 var2
应该反映var1
的值,反之亦然。我在指令中观察变量,以了解它在控制器中的变化。
问题是当指令中的监视变量发生变化时会产生一个循环(参见plunk控制台)。
为了防止这个循环,我可以在指令中创建两个范围变量var2Input
和var2Output
来读取/写入控制器中的var1
。只会var2Input
被观看,而我在var2Output
中更改的指令中更改了(在控制器中读取)。但我不想创建两个变量,因为它们总是具有相同的值。任何想法如何处理这个?
使用Javascript:
app.directive('someDirective', function () {
var directive = {};
directive.restrict = 'EA';
directive.scope = {
var2: '='
};
directive.template = 'This is var2: {{var2}} <br/> ' +
'<button ng-click="add1()">Add 1</button> <br/> ' +
'{{log}}';
directive.link = {};
directive.link.pre = function (scope, element, attrs) {};
directive.link.post = function (scope, element, attrs) {
scope.log = '';
scope.$watch('var2', function (newValue, oldValue) {
if (typeof newValue === 'undefined')
return;
scope.var2 = newValue * 10;
scope.log = scope.log + '<watched ' + newValue + '>';
});
scope.add1 = function() {
scope.var2++;
};
};
return directive;
});
答案 0 :(得分:2)
行。以下是应该执行您正在寻找的代码。看看代码然后我的解释如下:
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>AngularJS Example</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script>
var myApp = angular.module("myApp", []);
myApp.controller('appController', function($scope) {
$scope.var1 = 1;
$scope.add = function(amount) {
$scope.var1 += amount;
}
});
myApp.controller('watcherController', watcherController);
watcherController.$inject = ['$scope'];
function watcherController($scope) {
$scope.log = '';
$scope.$watch('var2', function (newValue, oldValue) {
if (typeof newValue === 'undefined') {
return;
}
$scope.log = $scope.log + '\nwatched ' + newValue;
});
$scope.add1 = function() {
$scope.var2++;
};
}
myApp.directive('watcher', watcherDirective );
function watcherDirective() {
return {
'restrict': 'EA',
'template': 'This is var2: {{var2}} <br/><hr/><button ng-click="add1()">Add 1</button><br/><hr/><h4>LOG:</h4><pre>{{log}}</pre>',
'controller': 'watcherController',
'scope': {
var2: '@'
},
'link': function ($scope, $element, $attrs, ctrl, transclude) {
$attrs.$observe('var2', function(newValue, one, two) {
$scope.var2 = parseInt(newValue,10)*10;
$scope.log += "\nChanged on the outside"+$scope.var2+' - '+(typeof $scope.var2);
});
}
};
}
</script>
</head>
<body ng-controller="appController">
<button ng-click="add(5)">Add from outer controller</button><br/>Var1:{{var1}}<br/><hr/>
<watcher var2="{{var1}}"></watcher>
</body>
</html>
每次更改$scope.$watch
时都会调用$scope.var2
,无论谁改变它,所以我们必须小心我们在该观察者内部所做的事情。
我现在显示外部控制器的$scope.var1
值,并添加了第二个按钮,用于更改外部控制器的$scope.var1
。每次更改时,该值都会传递给指令。
而不是使用双向绑定'var2': '='
我使用单向绑定'var2': '@'
这会将$scope.var1
的值转换为字符串并将其传递给指令。
然后,在指令中我添加了$attrs.$observe
,让我知道外部值何时发生变化。我必须使用parseInt()
将该值转换回数字。仅当外部世界更改指令的属性$attrs.$observer
的值时,才会调用var2
函数。
如果您需要双向绑定,则需要执行不同的操作。因此,如果指令需要能够修改外部控制器的$scope.var1
的值,那么我将需要演示其他内容。
如果这没有意义,请告诉我,我会修改我的答案。
修改后的答案:
这是一些修改后的代码。以下是解释:
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>AngularJS Example</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script>
var myApp = angular.module("myApp", []);
myApp.controller('appController', function($scope) {
$scope.var1 = 1;
$scope.add = function() {
$scope.var1++;
}
$scope.reset = function() {
$scope.var1 = 1;
}
});
//******************* BEGIN TWO WAY BINDING
myApp.controller('watcherController', watcherController);
watcherController.$inject = ['$scope'];
function watcherController($scope) {
$scope.log = '';
var doWatchCode = true;
$scope.$watch('var2', function (newValue, oldValue) {
if (typeof newValue === 'undefined') {
return;
}
if (doWatchCode) {
$scope.var2 = newValue * 10;
$scope.log = $scope.log + '\nvar2 watched newValue(' + newValue+') - $scope.var2('+$scope.var2+')';
doWatchCode = false;
}
else {
doWatchCode = true;
}
});
$scope.add1 = function() {
doWatchCode = false;
$scope.var2++;
};
}
myApp.directive('watcher', watcherDirective );
function watcherDirective() {
return {
'restrict': 'EA',
'template': 'This is var2: {{var2}} <br/><hr/><button ng-click="add1()">Add 1</button><br/><hr/><h4>LOG:</h4><pre>{{log}}</pre>',
'controller': 'watcherController',
'scope': {
var2: '='
},
'link': function ($scope, $element, $attrs, ctrl, transclude) {
$attrs.$observe('var2', function(newValue) {
$scope.log += "\nChanged on the outside"+newValue+' - '+(typeof newValue);
});
}
};
}
//******************* END TWO WAY BINDING
</script>
</head>
<body ng-controller="appController">
<button ng-click="reset()">Reset Var1</button><br/>
<button ng-click="add()">Add from outer controller</button><br/>Var1:{{var1}}<br/><hr/>
<watcher var2="var1"></watcher>
</body>
</html>
我在这里做的是添加一个门变量doWatchCode
,允许你的$watch
函数执行或不执行操作。
当doWatchCode
为true
时,您的$watch
函数可以执行任何需要执行的操作。如果它更改var2
的值,则必须将doWatchCode
的值更改为false
。这样做的原因是更改var2
会导致再次调用$watch
函数。但是,这次doWatchCode
将为false
并阻止var2
的值再次更新。在退出函数之前,doWatchCode
的值必须设置回true
。
在add
功能中,您必须将doWatchCode
设置为false
,以防止您的内部功能再次发生繁殖。
当var2
的值从外部doWatchCode
更改时,true
应该是$watch
,这将允许您的ArrayList<String> names = new ArrayList<>();
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
boolean access;
while (true) {
access = true;
System.out.println("Type your first name.");
String firstName = input.readLine();
//System.out.println();
System.out.println("Now type your last name.");
String lastName = input.readLine();
String fullName = firstName + " " + lastName;
if(names.size()==0) {
names.add(fullName);
continue;
}
for (String name : names) {
if (name.equals(fullName)) {
System.out.println("That is not your name. Please type in your real name.");
access = false;
break;
}
}
if(access) {
names.add(fullName);
System.out.println();
System.out.println(firstName + " " + lastName);
}
}
功能完成其工作。
如果有效,请告诉我。
答案 1 :(得分:1)
第一次只需要观察者即可获得第一次text
更改。之后你可以取消它。另外CodeMirror
是3d派对插件,您可以添加空 $timeout
来触发摘要周期。这是一个有效的固定演示:
var app = angular.module('app', []);
app.controller('myCtl', function($scope) {
$scope.text = "this is the text";
$scope.showText = function() {
alert($scope.text);
};
});
app.directive('editor', function ($timeout) {
var directive = {};
directive.restrict = 'EA';
directive.scope = {
text: '='
};
directive.template = '<textarea id="cm"> </textarea>';
directive.link = function (scope, element, attrs) {
scope.editor = CodeMirror.fromTextArea(document.getElementById('cm'), {
lineNumbers: true
});
scope.editor.setSize(300, 100);
var canceler = scope.$watch('text', function (newValue, oldValue) {
if (typeof newValue === 'undefined')
return;
scope.editor.setValue(newValue);
canceler();
});
scope.editor.on("change", function(cm, change) {
$timeout(function(){
scope.text = scope.editor.getValue();
});
});
};
return directive;
});