0

Given the following:

<div data-ng-repeat="val in vals">
      <div data-ng-class:{'myClass':isEngineOn(val)}>
          <span data-ng-show="isEngineOn(val)">yeah it's on</span>
          <span data-ng-show="!isEngineOn(val)"> standby</span>
          <button data-ng-disabled="isEngineOn(val)">Start engine</button>
      <div>
</div>

isEngineOn changes with websocket messages I receive from the server.

Is there a way to avoid evaluating isEngineOn, 4 times during each digest, per each value in the repeat? Something like initializing a variable or something?

2
  • When does isEngineOn change? Please provide isEngineOn code Commented Feb 15, 2015 at 16:18
  • everytime i receive a websocket msg from the server. I don't have the code, since the example is invented. Commented Feb 15, 2015 at 16:20

3 Answers 3

1

You can do that with simple CSS and without calling the function in the spans. I think thats much more efficient than a JavaScript solution, especially when you have a repeat over many elements because you can save bindings:

<div data-ng-repeat="val in vals">
    <div data-ng-class:{'myClass':isEngineOn(val)}>
        <span class="showWhenOn">yeah it's on</span>
        <span class="showWhenOff"> standby</span>
        <button onclick="alert('Starting...')">Start engine</button>
    </div>
</div>

CSS:

.showWhenOn {
    display: none;
}

.myClass .showWhenOn {
    display: inline;
}

.myClass .showWhenOff {
    display: none;
}

.myClass button {
    pointer-events: none;
    color: silver;
}

JS Fiddle

Sign up to request clarification or add additional context in comments.

7 Comments

that is good advice, the real case also contains some buttons which I have to disable though, and don't see a way of applying the disable property using css. I can, using the function <button data-ng-disabled="isEngineOn(val)"> StartEngine</button>, but i want to avoid it.
@dalvarezmartinez1 you can use the css property pointer-events: none for that
yes, but i can still click the button, even if the visual effect is like, you don't click it. btw i gave a thumb up, it's interesting what you're proposing, limit angular bindings by using css in a smarter way, i did not think about this
Nope, pointer-events does not change the way the button is displayed. This property controls the behavior of the button, so nothing will happen if you click on it.
well in my case it prints stuff, just the stuff i have in the data-ng-click, and it shows that the property applies (firebug).
|
0

Yes, just have a variable in the controller that holds the result, and update that variable when you receive an update from the server:

In your controller:

$scope.engineOn = isEngineOn();//also make sure to update from server whenever you need

Note that if your isEngineOn() function is no longer called from the view it doesn't need to be on the scope, it can be declared as a regular variable.

HTML:

<div data-ng-class="{'myClass':engineOn}">
      <span data-ng-show="engineOn">yeah it's on</span>
      <span data-ng-show="!engineOn"> standby</span>
<div>

EDIT 2: The ng-init, as you said, did not update on digest so I've taken a second approach.

I've taken the long way round, and created a corresponding array for your values and you can read from that:

  <div data-ng-repeat="val in vals" >
      <div data-ng-class="{'myClass':enginOn[val]}">
          <span data-ng-show="engineOn[val]">yeah it's on</span>
          <span data-ng-show="!engineOn[val]"> standby</span>
          <button data-ng-disabled="isEngineOn(val)">Start engine</button>
      </div>
</div>

Fiddle.

9 Comments

That won't work, isEngineOn function will not be updated every time digest is called, engineOn will be initial value forever
@karaxuna Hence the comment I placed, and the text above saying to update that variable.
fair enough, the thing is, the function has a parameter which depends on an ng-repeat, i will edit the question, sorry for that.
@dalvarezmartinez1 About a million times in a million places :) What error do you get?
@dalvarezmartinez1 Wait, there might be an issue, I'll update in a sec.
|
0

You can set watcher to variable that changes when you receive answer from server, for example:

scope.$watch(function(){ return <var that changes>; }, function(oldv, newv){
    if(oldv !== newv)
        scope.isEngineOn = <Calculate here>;
});

Then use:

<span data-ng-show="isEngineOn">

1 Comment

Better not to have a redundant watch, it's heavy on performance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.