【问题标题】:Angular.js ng-switch-when not working with dynamic data?Angular.js ng-switch-何时不使用动态数据?
【发布时间】:2014-03-01 05:26:50
【问题描述】:

我正在尝试让 Angular 根据我的数据生成 CSS 滑块。我知道数据在那里并且能够为按钮生成它,但是由于某种原因,代码不会填充 ng-switch-when。当我检查代码时,我看到了两次(我知道这是正确的,因为我只有两个项目):

<div ng-repeat="assignment in assignments" ng-animate="'animate'" class="ng-scope">
    <!-- ngSwitchWhen: {{assignment.id}} -->
</div>

我的实际代码:

<div ng-init="thisAssignment='one'">
     <div class="btn-group assignments" style="display: block; text-align: center; margin-bottom: 10px">
         <span ng-repeat="assignment in assignments">
              <button ng-click="thisAssignment = '{{assignment.id}}'" class="btn btn-primary">{{assignment.num}}</button>
         </span>
     </div>

     <div class="well" style="height: 170px;">
         <div ng-switch="thisAssignment">
              <div class="assignments">
                   <div ng-repeat="assignment in assignments" ng-animate="'animate'">
                        <div ng-switch-when='{{assignment.id}}' class="my-switch-animation">
                        <h2>{{assignment.name}}</h2>
                        <p>{{assignment.text}}</p>
                   </div>
              </div>
         </div>  
    </div>  
</div>

编辑:这就是我试图模仿的,虽然是动态数据。 http://plnkr.co/edit/WUCyCN68tDR1YzNnCWyS?p=preview

【问题讨论】:

  • 描述当你点击按钮时你期望在 DOM 中发生什么。从您的代码中不清楚您要做什么。您是否试图维持“选定”的分配?
  • 另外,请注意,您在 ng-repeats 中覆盖了变量。我的意思是,在外部块上,您将字符串“一”分配给assignment,但是在您的转发器块上,您拥有同名的迭代器变量assignment,然后您将其分配给块内。您应该尝试将用于跟踪被选中的属性的名称更改为 selectedAssignment 之类的名称。
  • 我认为我已经根据您提到的内容更改了我的代码,但我仍然不太清楚。上面修改的代码不起作用。
  • 您在下面阅读我的回答了吗? Ng-switch 用于硬编码(非动态)条件。尝试查看文档,看看其他指令会根据特定条件动态交换 DOM,例如 ng-if。
  • 好的。我不确定您最近的评论是否否定了您之前提到的任何内容。我会看看。对此感到抱歉。

标签: angularjs angularjs-ng-repeat ng-switch


【解决方案1】:

来自docs——

请注意,要匹配的属性值不能是表达式。他们是 解释为要匹配的文字字符串值。例如,ng-switch-when="someVal" 将匹配字符串“someVal”而不是表达式的值 $scope.someVal.

换句话说,ng-switch 用于在模板中硬编码条件。

你会这样使用它:

<div class="assignments">
  <div ng-repeat="assignment in assignments" ng-animate="'animate'">
    <div ng-switch="assignment.id">
      <div ng-switch-when='1' class="my-switch-animation">
      <h2>{{assignment.name}}</h2>
      <p>{{assignment.text}}</p>
    </div>
  </div>
</div>

现在这可能不完全适合您的用例,因此您可能需要重新考虑您的策略。

Ng-If 可能是您所需要的——另外,您需要注意"isolated" scopes。基本上,当您使用某些指令(例如 ng-repeat)时,您会创建与其父级隔离的新范围。因此,如果您在转发器内更改 thisAssignment,您实际上是在更改特定重复块内的变量,而不是整个控制器。

这是您的目标demo

请注意,我将 selected 属性分配给 things 数组(它只是一个对象)。


2014 年 12 月 12 日更新:添加新代码块以阐明 ng-switch 的使用。上面的代码示例应该被认为是要做的。

正如我在评论中提到的。 Switch 应该被认为与 JavaScript 开关完全一样。它用于硬编码的切换逻辑。因此,例如在我的示例帖子中,只有几种类型的帖子。您应该提前知道要打开的值的类型。

<div ng-repeat="post in posts">
  <div ng-switch on="post.type">

    <!-- post.type === 'image' -->
    <div ng-switch-when="image" class="post post-image">
      <img ng-src="{{ post.image }} />
      <div ng-bind="post.content"></div>
    </div>

    <!-- post.type === 'video' -->
    <div ng-switch-when="video" class="post post-video">
      <video ng-src="{{ post.video }} />
      <div ng-bind="post.content"></div>
    </div>
    
    <!-- when above doesn't match -->
    <div ng-switch-default class="post">
      <div ng-bind="post.content"></div>
    </div>
  </div>
</div>

您可以使用ng-if 实现相同的功能,您的工作是决定在您的应用程序中什么是有意义的。在这种情况下,后者更简洁,但也更复杂,如果模板更复杂,你会看到它变得更加复杂。基本区别是ng-switch 是声明性的,ng-if 是命令性的。

<div ng-repeat="post in posts">
  <div class="post" ng-class="{
      'post-image': post.type === 'image', 
      'post-video': post.type === 'video'">
    <video ng-if="post.type === 'video'" ng-src="post.video" />
    <img ng-if="post.type === 'image'" ng-src="post.image" />
    <div ng-bind="post.content" />
  </div>
</div>

【讨论】:

  • 啊!太感谢了!有点类似于加入(我认为),但它只是没有通过。非常感谢。
  • 可以修改此方法以使用嵌套数据吗?即我想使用 ng-repeat 来显示用户列表,当点击用户时它会显示一些个人资料信息?
  • 我们为什么要有这个功能?我觉得它促进了魔法值......如果开关依赖于 i18n 翻译值怎么办?
  • 你能解释一下你所说的“神奇”值是什么意思吗?开关用于应用程序中的硬编码逻辑。假设您有一个 ng-repeat,它会遍历帖子。你有几种类型的帖子。可能是文本类型、图像类型和视频类型。在 switch 语句中,您将使用switch on="post.type",然后您的when 子句将用于“文本”、“图像”和“视频”——也许您会将“文本”保留为默认类型。 i18n 不应该进入等式,因为你不应该打开用户输入。
  • “神奇”值是在代码中的多个位置硬编码的值,而不是集中为常量。我想使用 AngularJS 内容作为我的 ng-switch-when 语句的模型数据。我不能,这让我很难过:(。无论如何我都需要常量,但现在值是重复的。
【解决方案2】:

乔恩绝对是正确的。 Angular 不支持动态 ngSwitchWhen 值。但我想要它。我发现使用我自己的指令代替ngSwitchWhen 实际上非常简单。它不仅支持动态值,而且还支持每个语句的多个值(类似于 JS 切换失败)。

需要注意的是,它只在编译时计算一次表达式,因此您必须立即返回正确的值。出于我的目的,这很好,因为我想使用应用程序中其他地方定义的常量。可能可以对其进行修改以动态重新评估表达式,但这需要使用ngSwitch 进行更多测试。

我使用的是 angular 1.3.15,但我使用 angular 1.4.7 进行了快速测试,它在那里也运行良好。

Plunker Demo

代码

module.directive('jjSwitchWhen', function() {
    // Exact same definition as ngSwitchWhen except for the link fn
    return {
        // Same as ngSwitchWhen
        priority: 1200,
        transclude: 'element',
        require: '^ngSwitch',
        link: function(scope, element, attrs, ctrl, $transclude) {
            var caseStms = scope.$eval(attrs.jjSwitchWhen);
            caseStms = angular.isArray(caseStms) ? caseStms : [caseStms];

            angular.forEach(caseStms, function(caseStm) {
                caseStm = '!' + caseStm;
                ctrl.cases[caseStm] = ctrl.cases[caseStm] || [];
                ctrl.cases[caseStm].push({ transclude: $transclude, element: element });
            });
        }
    };
});

用法

控制器
  $scope.types = {
      audio: '.mp3', 
      video: ['.mp4', '.gif'],
      image: ['.jpg', '.png', '.gif'] // Can have multiple matching cases (.gif)
  };
模板
  <div ng-switch="mediaType">
    <div jj-switch-when="types.audio">Audio</div>

    <div jj-switch-when="types.video">Video</div>

    <div jj-switch-when="types.image">Image</div>

    <!-- Even works with ngSwitchWhen -->
    <div ng-switch-when=".docx">Document</div>

    <div ng-switch-default>Invalid Type</div>
  <div>

【讨论】:

    猜你喜欢
    • 2016-01-20
    • 1970-01-01
    • 2013-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多