Angularjs:ngDialog只绑定和修改对象,而不是基本变量



我已经找到了这个问题的"解决方案";我只是希望有人能够提供它起作用的原因。

这个jsFiddle演示了这个问题: http://jsfiddle.net/s1ca0h9x/137/

.HTML

<div data-ng-app="myApplication">
<div data-ng-controller="MainController">
<a href="" ng-click="ShowNgDialog()">Click Here</a>
<input type="text" ng-model="accountNum" />
<span>{{accountNum}}</span>
</div>
</div>

ANGULARJS

var myApplication = angular.module('myApplication', ['ngDialog']);
myApplication.controller('MainController', function ($scope, ngDialog) {
$scope.accountNum = 'test';
$scope.ShowNgDialog = function () {
ngDialog.open({            
template: '<div><input type="text" ng-model="accountNum"/></div>',
plain: true,
scope:$scope
});
}    
});

当我尝试从对话框中操作范围变量(在本例中为:$scope.accountNum = 'test'(时,它不会将其绑定/保存回模型。

。但是,当我将该变量更改为对象时,事情就会神奇地工作,如以下演示所示: http://jsfiddle.net/s1ca0h9x/138/

.HTML

<div data-ng-app="myApplication">
<div data-ng-controller="MainController">
<a href="" ng-click="ShowNgDialog()">Click Here</a>
<input type="text" ng-model="FormData.accountNum" />
<span>{{FormData.accountNum}}</span>
</div>
</div>

ANGULARJS

var myApplication = angular.module('myApplication', ['ngDialog']);
myApplication.controller('MainController', function ($scope, ngDialog) {
$scope.FormData={accountNum: ''};
$scope.ShowNgDialog = function () {
ngDialog.open({            
template: '<div><input type="text" ng-model="FormData.accountNum"/></div>',
plain: true,
scope:$scope
});
}    
});

除了尝试ngDialog.openConfirm等之外,我还使用链接到文件的模板测试了这两个选项,而不是使用plain:true。我基本上重建了在这里找到的解决方案 ngDialog $scope使用 scope 时,ngModel 字段中的变量不会$dialog更新:$scope一块一块,最后似乎唯一有效的更改是使用对象而不是基本范围变量。 我是否处理错了,或者错过了数据绑定的一些基本方面?

我认为这与绑定无关。我将解释当我深入研究ngDialogAngularJS的代码时所理解的内容。

我认为第一种情况没有像您期望的那样工作,因为$scope.accountNum = 'test';是一个简单的字符串,它是一个原始类型并且不可变(ref(,或者换句话说是不可变的:

可变是一种可以更改的变量。在 JavaScript 中,只有 对象和数组是可变的,而不是基元值。 (您可以使变量名称指向新值,但之前的 值仍保存在内存中。因此需要垃圾收集。

可变对象是其状态在 创建

不可变对象是其状态无法更改的对象,一旦 对象已创建。

字符串和数字是不可变的。

因此,简而言之,这就是第一个变体无法按您想要的方式工作的原因:)


现在让我们来看看 ngDialog 的这段代码,它是open((方法的一部分:

var scope;
scopes[dialogID] = scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();

在您的情况下,我们正在调用options.scope.$new(),因为您在打开对话框时在选项中指定了scope

现在让我们去检查这个角度代码:

$new: function (isolate, parent) {
var child;  
parent = parent || this;
if (isolate) {
child = new Scope();
child.$root = this.$root;
} else {
if (!this.$$ChildScope) {
this.$$ChildScope = createChildScopeClass(this); // <---- WE ARE COMING HERE NOW
}
child = new this.$$ChildScope();
}
...

函数createChildScopeClass看起来像:

function createChildScopeClass(parent) {
function ChildScope() {
this.$$watchers = this.$$nextSibling =
this.$$childHead = this.$$childTail = null;
this.$$listeners = {};
this.$$listenerCount = {};
this.$$watchersCount = 0;
this.$id = nextUid();
this.$$ChildScope = null;
}
ChildScope.prototype = parent; /* <--- They simply assign the derived scope 
as prototype of the new one (which is going to be the scope of the ngDialog) */
return ChildScope;
}

我们可以看到,function createChildScopeClass()只是将父作用域的原型分配给新的(这将是打开的 ngDialog 的作用域(

还有一个演示可变性和不变性的示例:

var test = 'test'; 
var test2 = test;
test2 = 'new value';
console.log('test = ' + test + ' // test2 = ' + test2);
var testObj = {test: 'test'};
var test2Obj = testObj;
test2Obj.test = 'new value';
console.log('testObj.test = ' + testObj.test + ' // test2Obj.test = ' + test2Obj.test);

结论

如果希望绑定在派生作用域中工作,请使用父作用域中的对象数组。使用 AngularJS 的示例:

var app = angular.module('sample', []);
app.controller('AppController', ['$scope', function($scope) {
$scope.primitive = 'test';
$scope.obj = {
test: 'test initial'
};
$scope.newScope = $scope.$new();
$scope.newScope.primitive = 'test 2';
$scope.newScope.obj.test = 'updated value';
}]);
app.run();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="sample">
<div ng-controller="AppController">
<table>
<thead><tr><th>Property</th><th>Value</th><th></th></tr></thead>
<tbody>
<tr>
<td>primitive</td>
<td>{{ primitive }}</td>
<td><input type="text" ng-model="primitive"></td>
</tr>
<tr>
<td>obj.test</td>
<td>{{ obj.test }}</td>
<td><input type="text" ng-model="obj.test"></td>
</tr>
<tr>
<td>newScope.primitive</td>
<td>{{ newScope.primitive }}</td>
<td><input type="text" ng-model="newScope.primitive"></td>
</tr>
<tr>
<td>newScope.obj.test</td>
<td>{{ newScope.obj.test }}</td>
<td><input type="text" ng-model="newScope.obj.test"></td>
</tr>
</tbody>
</table>
</div>
</div>

对我来说,有效的是在基本控制器中创建一个函数,并从ngDialog控制器调用该函数。

前任:

myApplication.controller('MainController', function ($scope, ngDialog) {
$scope.accountNum = 'test';
$scope.ShowNgDialog = function () {
ngDialog.open({            
template: '<div><input type="text" ng-model="accountNum"/></div>',
plain: true,
scope:$scope,
controller: ['$scope',
function ($scope) {
$scope.updateVar();
}]
});
};
$scope.updateVar = function(){
$scope.accountNum = "changed";
}
});

最新更新