Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular scope and ng-click / ng-show to set multiple divs

I am looking for some help with my code I have so far.

The main objective is to be able to click on any Plus icon and have it place a cover over all other div blocks.

And when a plus icon is clicked it will also show a div block to the right.

As you will see when block 2 is clicked it does all that is intended.

I am looking for an efficient way to do this with Angular when any plus icon is clicked.

This is just a small sample I show here, in reality there would be 10 to 20 blocks to cover.

If someone could see a way to use less code here and make better use of the scope, this would be greatly appreciated.

I have looked at many options like in this post here.

Tried this but it doesn't want to work...

data-ng-class="{coverThisBlock: value2 == 'off',coverThisBlock: value == 'on'}"

If I had to use this type of option with even say 10 blocks, it would be a real mess.

The main Questions

Is there a better Angular way for this to work... when any plus icon is clicked it changes scope to then be used by ngclass and ng-show?

How to correctly wire up scope for this example?

Many Thanks.

I have set up a working FIDDLE HERE.

enter image description here

HERE IS THE FINAL WORKING EXAMPLE by Avijit Gupta.

enter image description here

<div class="container" ng-app="plusMinusApp"  ng-controller="plusMinusController">

<div class="row" ng-init="value1 = 'off'">
 <!--<div class="col-xs-4" data-ng-class="{coverThisBlock: value2 == 'off',coverThisBlock: value == 'on'}"> --> 
    <div class="col-sm-4 col-xs-6" data-ng-class="{coverThisBlock: value2 == 'off'}">    
        <div class="divClass" 
        data-ng-click="(selectBlock(1)) ; (status1 = !status1) ; (value1 = { 'on': 'off', 'off':'on'}[value1])" 
        data-ng-class="{'active-selection': status1 == activeClass}">
        1
        </div>
        <i ng-click="(selectBlock(1)) ; (status1 = !status1) ; (value1 = { 'on': 'off', 'off':'on'}[value1])" 
        class="btn btn-primary text-center fa" 
        ng-class="{'fa-minus': status1, 'fa-plus': !status1}"></i>
    </div>
    <div  ng-show="value1 == 'on'" class="col-xs-4 textdiv">Hello</div>
</div>

<div class="row" >
    <div class="col-sm-4 col-xs-6" ng-init="value2 = 'on'">    
        <div class="divClass" 
        data-ng-click="(value2 = { 'on': 'off', 'off':'on'}[value2])" 
        data-ng-class="{'active-selection': value2 == 'off'}">
        2
        </div>
        <i ng-click="(value2 = { 'on': 'off', 'off':'on'}[value2])" 
        class="btn btn-primary text-center fa" 
        ng-class="{'fa-minus': (value2 == 'off'), 'fa-plus': value2}"></i>
    </div>
    <div  ng-show="value2 == 'off'" class="col-xs-3 textdiv">Hello</div>
</div>

<div class="row">  
    <div class="col-sm-4 col-xs-6" data-ng-class="{'coverThisBlock': value2 == 'off'}">    
        <div class="divClass" 
        data-ng-click="(selectBlock(3)) ; (status3 = !status3)" 
        data-ng-class="{'active-selection': !status3 == activeClass}">
        3
        </div>
        <i ng-click="(selectBlock(3)) ; (status3 = !status3)" 
        class="btn btn-primary text-center fa" 
        ng-class="{'fa-minus': status3, 'fa-plus': !status3}"></i>
    </div>
</div>

<div class="row"> 
    <div class="col-sm-4 col-xs-6" data-ng-class="{'coverThisBlock': value2 == 'off'}">    
        <div class="divClass" 
        data-ng-click="(selectBlock(1)) ; (status4 = !status4)" 
        data-ng-class="{'active-selection': status4 == activeClass}">
        4
        </div>
        <i ng-click="(selectBlock(1)) ; (status4 = !status4)" 
        class="btn btn-primary text-center fa" 
        ng-class="{'fa-minus': status4, 'fa-plus': !status4}"></i>
    </div>
    <div  ng-show="status4" class="col-xs-4 textdiv">Hello</div>   
</div>

<div class="row" ng-init="value = 'off'">
    <div class="col-sm-4 col-xs-6" data-ng-class="{'coverThisBlock': value2 == 'off'}">    
        <div class="divClass" 
        data-ng-click="(selectBlock(1)) ; (status = !status) ; (value = { 'on': 'off', 'off':'on'}[value])" 
        data-ng-class="{'active-selection': status == activeClass}">
        5
        </div>
        <i ng-click="(selectBlock(1)) ; (status = !status) ; (value = { 'on': 'off', 'off':'on'}[value])" 
        class="btn btn-primary text-center fa" 
        ng-class="{'fa-minus': status, 'fa-plus': !status}"></i>
    </div>
    <div  ng-show="value == 'on'" class="col-xs-4 textdiv">Hello</div>
</div>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="js/plusMinusApp.j"></script>
<script>

var myModule = angular.module('plusMinusApp', []);
myModule.controller('plusMinusController', function ($scope) {

    $scope.status  = false;    
    $scope.status1 = false;
    $scope.status2 = false;
    $scope.status3 = false;
    $scope.status4 = false;    

$scope.blocks = [{
    id: '1',
    block: "1",
  }, {
    id: '2',
    block: "2",
  }, {
    id: '3',
    block: "3",
  }, {
    id: '4',
    block: "4",
  }, {
    id: '5',
    block: "5"
  }];
 // $scope.activeClass = 0;  
  $scope.selectBlock = function(id) {
    $scope.activeClass = id;
    console.log(id);
  };  
});    
</script>  

TO ANSWER THE QUESTION TO DO WITH NG-REPEAT

Can ng-repeat use multiple css classes for each different div

Apparently it can.

By using the scope id like this...

<div class="block-{{block.id}}">

and the css like this...

.block-1 {...

WORKING FIDDLE OF THIS HERE

like image 518
AngularJR Avatar asked Dec 30 '15 04:12

AngularJR


1 Answers

EDIT (Based on asker's comment):

UPDATED FIDDLE

  1. only one can be clicked at a time? Or if another is open/clicked the first opened is reset and closed

This simplifies your code by almost 2x.

Initial State:

  • None of the blocks are selected.
  • None of the blocks are covered.

Code:

$scope.setToInitialState = function() {
  $scope.blocks.forEach(function(block) {
    $scope.isSelected[block.id] = false;
    $scope.isCovered[block.id] =  false;
  });
};

Touched State:

  • Toggle the selected state of the clicked block. (toggle between select and deselect).
  • If selected, then cover and deselect all the other blocks.
  • If deselected, then bring the app to the initial state.

Code:

$scope.selectBlock = function(id) {
  $scope.isSelected[id] = !$scope.isSelected[id];
  $scope.isCovered[id] = false;
  if ($scope.isSelected[id]) {
    $scope.blocks.forEach(function(block) {
      if (block.id !== id) {
        $scope.isCovered[block.id] = true;
        $scope.isSelected[block.id] = false;
      }    
    });
  }
  else {
    $scope.setToInitialState();
  }
};
  1. The demo uses all the same set block sizes, but the actual use all div Blocks are different heights and widths. And each block is a different image

You should consider using ng-src.

I am assuming that you might be retreiving all this content from the DB. Then, if possible, you may place each of your image inside a div of fixed size, so that they all come out to be of the same size.

  1. Plus the display is divided into 2 vertical half screen sections

That can be set right tweaking a little bit of css.


ORIGINAL ANSWER:

WORKING FIDDLE

Let's say your app has 2 states:

  1. Initial state (untouched)
  2. Touched state

Initially, you are in the Initial state:

  • No right divs are shown.
  • All the icons are 'plus' (no 'minus')
  • None of the blocks are covered.

Code:

$scope.setToInitialState = function() {
  $scope.plusCount = 0;
  $scope.blocks.forEach(function(block) {
    $scope.isPlus[block.id] = true;
    $scope.isShowDiv[block.id] = false;
    $scope.isCoverBlock[block.id] = false;
    $scope.plusCount += 1;
  });
};

When you are in the Touched state:

  • All those blocks are covered, which have a 'plus' icon.
  • The right divs of only those blocks are shown, which are not covered.

Code:

// Run when user clicks on the 'plus' or 'minus' icon.
$scope.selectBlock = function(id) {
  $scope.isPlus[id] = !$scope.isPlus[id]; // toggle between 'plus' and 'minus' icons
  if ($scope.isPlus[id]) {
    $scope.plusCount += 1;
  }
  else {
    $scope.plusCount -= 1;
  }
  $scope.blocks.forEach(function(block) {

    if ($scope.isPlus[block.id]) {
      $scope.isCoverBlock[block.id] = true;
    }
    else {    
      $scope.isCoverBlock[block.id] = false;
    }
    $scope.isShowDiv[block.id] = !$scope.isCoverBlock[block.id];

  });
};

So, basically when the user interacts with the view and actually clicks on the icon, then he/she goes to the touched state (the above code is run).

Only when all the icons are 'plus', then the user must be sent to the initial state:

if ($scope.plusCount === $scope.blocks.length) {
  $scope.setToInitialState();
}

Changes in html:

  1. Add ng-init="setToInitialState()" to the outermost div, so that we are in the initial state initially.

Code:

<div class="container" ng-app="plusMinusApp"  ng-controller="plusMinusController" ng-init="setToInitialState()">
  1. Use ng-repeat instead of copy-pasting code for each block:

Code:

<div class="row" ng-repeat="block in blocks">
    <div class="col-sm-4 col-xs-6" data-ng-class="{ 'coverThisBlock': isCoverBlock[block.id]}">    
        <div class="divClass" 
        data-ng-class="{'active-selection': !isPlus[block.id]}">
        {{block.id}}
        </div>
        <i data-ng-click="selectBlock(block.id)" 
        class="btn btn-primary text-center fa" 
        data-ng-class="{'fa-minus': !isPlus[block.id], 'fa-plus': isPlus[block.id]}"></i>
    </div>
    <div data-ng-show="isShowDiv[block.id]" class="col-xs-3 textdiv">Hello</div>
</div>

Hope it helps you!

like image 159
Avijit Gupta Avatar answered Sep 27 '22 22:09

Avijit Gupta