Angular.js ng-switch-when not working with dynamic data?

前端 未结 2 1058
忘掉有多难
忘掉有多难 2020-12-05 02:54

I\'m trying to get Angular to generate a CSS slider based on my data. I know that the data is there and am able to generate it for the buttons, but the code won\'t populate

相关标签:
2条回答
  • 2020-12-05 03:05

    From the docs —

    Be aware that the attribute values to match against cannot be expressions. They are interpreted as literal string values to match against. For example, ng-switch-when="someVal" will match against the string "someVal" not against the value of the expression $scope.someVal.

    So in other words, ng-switch is for hardcoding conditions in your templates.

    You would use it like so:

    <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>
    

    Now this might not fit your use case exactly, so it's possible you'll have to rethink your strategy.

    Ng-If is probably what you need — also, you need to be aware of "isolated" scopes. Basically when you use certain directives, like ng-repeat, you create new scopes which are isolated from their parents. So if you change thisAssignmentinside a repeater, you're actually changing the variable inside that specific repeat block and not the whole controller.

    Here's a demo of what you're going for.

    Notice I assign the selected property to the things array (it's just an object).


    Update 12/12/14: Adding a new block of code to clarify the use of ng-switch. The code example above should be considered what not to do.

    As I mentioned in my comment. Switch should be thought about exactly like a JavaScript switch. It's for hardcoded switching logic. So for instance in my example posts, there are only going to be a few types of posts. You should know a head of time the types of values you are going to be switching on.

    <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>
    

    You could implement this same functionality with ng-if, it's your job to decide what makes sense within your application. In this case the latter is much more succinct, but also more complicated, and you could see it getting much more hairy if the template were any more complex. Basic distinction is ng-switch is declarative, ng-if is imperative.

    <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>
    
    0 讨论(0)
  • 2020-12-05 03:12

    Jon is definitely right on. Angular does not support dynamic ngSwitchWhen values. But I wanted it to. I found it actually exceptionally simple to use my own directive in place of ngSwitchWhen. Not only does it support dynamic values but it supports multiple values for each statement (similar to JS switch fall-throughs).

    One caveat, it only evaluates the expression once upon compile time, so you must return the correct value immediately. For my purposes this was fine as I was wanting to use constants defined elsewhere in the application. It could probably be modified to dynamically re-evaluate the expressions but that would require more testing with ngSwitch.

    I am use angular 1.3.15 but I ran a quick test with angular 1.4.7 and it worked fine there as well.

    Plunker Demo

    The Code

    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 });
                });
            }
        };
    });
    

    Usage

    Controller
      $scope.types = {
          audio: '.mp3', 
          video: ['.mp4', '.gif'],
          image: ['.jpg', '.png', '.gif'] // Can have multiple matching cases (.gif)
      };
    
    Template
      <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>
    
    0 讨论(0)
提交回复
热议问题