Angularjs - ng-disabled 不像预期那样起作用。

10
我是一个有用的助手,可以为您翻译文本。
我正在尝试禁用文件input标签,在用户选择文件后。
HTML:
<div ng-controller='firstController'>
    <div ng-controller='secondController'>
      <input type="file" name="file" upload class="theFileInput" ng-disabled="fileInMemory">
    </div>
</div>

JS,第一个控制器:

$scope.fileInMemory = false; // tracks if user selected a file for upload, but didn't upload it
$rootScope.$on('fileAdded', function () {
     $scope.fileInMemory = true;
     console.log($scope.fileInMemory);
});

upload是一个指令。

页面加载时,ng-disabled应该为false,当fileInMemory被更改时,input标签仍未被禁用。 console.log显示fileInMemory的值正在按预期更改。

我尝试过的方法

<input type="file" name="file" class="theFileInput" ng-disabled="'fileInMemory'">

fileInMemory为假时,立即禁用该字段。

<input type="file" name="file" class="theFileInput" ng-disabled="fileInMemory == 'true'">

不工作。
<input type="file" name="file" class="theFileInput" ng-disabled="{{fileInMemory}}">

还是不起作用。

禁用标签的最佳方法是什么?

找到了问题

看起来问题出在作用域上。 我有一个带有其范围的firstController,其中包含有其范围的secondController,以及upload指令的input标签,显然创建了它自己的作用域,并且没有看到firstController的作用域。

secondControllerupload都是一般的控件器,因此不会继承firstController

我想我最好的解决方案是在secondController中添加一些通用处理程序,基于input字段上的附加属性,在需要时禁用它。


1
请翻译以下与程序相关的内容从英文到中文。只返回已翻译的文本:不使用表达式,只使用变量。 - charlietfl
我认为文件输入不在 fileInMemory 所属的范围内。你能制作一个演示吗? - Alborz
@Alborz,我该如何检查它们是否在同一范围内?当我将fileInMemory的值输出到HTML时,它正常显示,具有正确的值。 - Neara
是否涉及任何子作用域?如果存在子作用域,最好使用具有fileInMemory属性的对象。 - charlietfl
1
你使用嵌套作用域吗?使用对象而不是基本类型。 - Alborz
显示剩余2条评论
8个回答

5

由于它在事件内部被改变,你需要利用$apply来实现:

$scope.fileInMemory = false;
$rootScope.$on('fileAdded', function () {
    $scope.$apply(function() {
        $scope.fileInMemory = true;
        console.log($scope.fileInMemory);
    });
});

更新:为了解决隔离作用域引起的问题,请将fileInMemory移动到$rootScope中:

$rootScope.fileInMemory = false;
$rootScope.$on('fileAdded', function () {
    $rootScope.$apply(function() {
        $rootScope.fileInMemory = true;
        console.log($scope.fileInMemory);
    });
});

我尝试使用$scope.$apply,但仍然无法正常工作。我认为元素上的directive会创建自己的隔离作用域。 - Neara
@Neara,修复方法是将变量移动到$rootScope而不是$scope - Mike Perrenoud

2

如果问题与作用域有关,请尝试使用“controller as”语法:

<div ng-controller='firstController as first'>
    <div ng-controller='secondController as second'>
      <input type="file" name="file" upload class="theFileInput" ng-disabled="first.fileInMemory">
    </div>
</div>

链接: AngularJs "controller as" 语法 - 澄清?


1

你试过这样吗?

<input type="file" name="file" class="theFileInput" ng-disabled="fileInMemory">

这是一个工作示例 演示


我已经发布了演示链接,你能分享你的代码吗?也许值不在正确的范围内? - Narek Mamikonyan
我添加了更多的代码,我有一个控制器在另一个控制器内部,并且变量被外部控制器操纵。这是一个问题吗? - Neara
是的,如果您有嵌套控制器,您应该在变量之前使用控制器名称,例如ctrl2.fileInMemory。 - Narek Mamikonyan

1
简而言之,每个ngController都会创建一个新的子作用域。由secondController创建的作用域将覆盖firstController中的fileInMemory值。因此,更改不会传播,其值被锁定false。通过使用controllerAs语法,可以轻松避免这种情况。

0

你试过这个吗:

HTML:

<div ng-controller='firstController'>
    <div ng-controller='secondController'>
      <input type="file" name="file" upload class="theFileInput" ng-disabled="fileInMemory.disabled">
    </div>
</div>

控制器:

$scope.fileInMemory = { disabled: false }; 

$rootScope.$on('fileAdded', function () {
     $scope.fileInMemory.disabled = true;
     console.log($scope.fileInMemory);
});

这里有一个可用的示例


0

请尝试以下操作

ng-disabled="fileInMemory"

0

使用对象而不是原始类型。

在第一个控制器中:

$scope.model = {};
$scope.model.fileInMemory = false; 
$rootScope.$on('fileAdded', function () {
        $scope.model.fileInMemory = true;
        console.log($scope.model.fileInMemory);
    });

<div ng-controller='firstController'>
    <div ng-controller='secondController'>
      <input type="file" name="file" class="theFileInput" ng-disabled="model.fileInMemory">
    </div>
</div>

我尝试过这个,但它仍然不起作用。我还尝试了首先通过控制器引用:firstController.model.fileInMemory - Neara
如果可能的话,请发布一个演示。 - Alborz

-1

您的模型在控制台上被更改,但在视图中没有反映,因为这个更改是在 Angular 应用程序范围之外发生的。解决方法是在 $rootScope 上调用 $apply,以确保视图更新此事件从 Angular 应用程序范围之外调用。

// Something like this
$rootScope.$apply(function() {
  $rootScope.fileInMemory = true;
  // Now it'll be changed in views too
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接