114

I have a form for replying to messages that I want to show only when isReplyFormOpen is true, and everytime I click the reply button I want to toggle whether the form is shown or not. How can I do this?

liamzebedee
  • 14,010
  • 21
  • 72
  • 118

6 Answers6

220

You just need to toggle the value of "isReplyFormOpen" on ng-click event

<a ng-click="isReplyFormOpen = !isReplyFormOpen">Reply</a>
 <div ng-show="isReplyFormOpen" id="replyForm">
   </div>
tom redfern
  • 30,562
  • 14
  • 91
  • 126
Nitu Bansal
  • 3,826
  • 3
  • 18
  • 24
  • I was using exactly this, but for some reason the local boolean in ng-click was "overriding" the one I declared in the controller $scope. The problem disappears if I do the toggle via a function of the controller: ng-click="toggleBoolean()". Any idea why? – antoine Feb 12 '15 at 00:54
  • have you set Boolean value with default in controller? set $scope.isReplyFormOpen =falsel first time in controller function.and try. – Nitu Bansal Feb 12 '15 at 07:24
  • 1
    Oh, I did define the Boolean in the controller. The weird thing is that this default value was read correctly by the ng-show on page load, but then after clicking on ng-click it would update only this ng-show, and not others in the page (all watching the same Boolean—at least in theory)... – antoine Feb 12 '15 at 19:02
  • 3
    Solved it. Because my ng-click was nested in an ng-repeat, it created a child scope which hides the parent Boolean *when you attempt to change its value*. See https://stackoverflow.com/questions/15388344/behavior-of-assignment-expression-invoked-by-ng-click-within-ng-repeat/15394239. According to Angular best practices, you should treat $scope as read-only in directives. – antoine Feb 13 '15 at 21:37
  • I use your trick with `ng-class` : `` +1 . Thank you : ) ♥. – نرم افزار حضور و غیاب Jun 15 '16 at 00:18
30

Basically I solved it by NOT-ing the isReplyFormOpen value whenever it is clicked:

<a ng-click="isReplyFormOpen = !isReplyFormOpen">Reply</a>

<div ng-init="isReplyFormOpen = false" ng-show="isReplyFormOpen" id="replyForm">
    <!-- Form -->
</div>
lorem monkey
  • 3,942
  • 3
  • 35
  • 49
liamzebedee
  • 14,010
  • 21
  • 72
  • 118
17

If based on click here it is:

ng-click="orderReverse = orderReverse ? false : true"
josliber
  • 43,891
  • 12
  • 98
  • 133
Andrii Motsyk
  • 439
  • 5
  • 6
5

It's worth noting that if you have a button in Controller A and the element you want to show in Controller B, you may need to use dot notation to access the scope variable across controllers.

For example, this will not work:

<div ng-controller="ControllerA">
  <a ng-click="isReplyFormOpen = !isReplyFormOpen">Reply</a>

  <div ng-controller="ControllerB">
    <div ng-show="isReplyFormOpen" id="replyForm">
    </div>
  </div>

</div>

To solve this, create a global variable (ie. in Controller A or your main Controller):

.controller('ControllerA', function ($scope) {
  $scope.global = {};
}

Then add a 'global' prefix to your click and show variables:

<div ng-controller="ControllerA">
  <a ng-click="global.isReplyFormOpen = !global.isReplyFormOpen">Reply</a>

  <div ng-controller="ControllerB">
    <div ng-show="global.isReplyFormOpen" id="replyForm">
    </div>
  </div>

</div>

For more detail, check out the Nested States & Nested Views in the Angular-UI documentation, watch a video, or read understanding scopes.

James Gentes
  • 7,528
  • 7
  • 44
  • 64
0

If you have multiple Menus with Submenus, then you can go with the below solution.

HTML

          <ul class="sidebar-menu" id="nav-accordion">
             <li class="sub-menu">
                  <a href="" ng-click="hasSubMenu('dashboard')">
                      <i class="fa fa-book"></i>
                      <span>Dashboard</span>
                      <i class="fa fa-angle-right pull-right"></i>
                  </a>
                  <ul class="sub" ng-show="showDash">
                      <li><a ng-class="{ active: isActive('/dashboard/loan')}" href="#/dashboard/loan">Loan</a></li>
                      <li><a ng-class="{ active: isActive('/dashboard/recovery')}" href="#/dashboard/recovery">Recovery</a></li>
                  </ul>
              </li>
              <li class="sub-menu">
                  <a href="" ng-click="hasSubMenu('customerCare')">
                      <i class="fa fa-book"></i>
                      <span>Customer Care</span>
                      <i class="fa fa-angle-right pull-right"></i>
                  </a>
                  <ul class="sub" ng-show="showCC">
                      <li><a ng-class="{ active: isActive('/customerCare/eligibility')}" href="#/CC/eligibility">Eligibility</a></li>
                      <li><a ng-class="{ active: isActive('/customerCare/transaction')}" href="#/CC/transaction">Transaction</a></li>
                  </ul>
              </li>
          </ul>

There are two functions i have called first is ng-click = hasSubMenu('dashboard'). This function will be used to toggle the menu and it is explained in the code below. The ng-class="{ active: isActive('/customerCare/transaction')} it will add a class active to the current menu item.

Now i have defined some functions in my app:

First, add a dependency $rootScope which is used to declare variables and functions. To learn more about $roootScope refer to the link : https://docs.angularjs.org/api/ng/service/$rootScope

Here is my app file:

 $rootScope.isActive = function (viewLocation) { 
                return viewLocation === $location.path();
        };

The above function is used to add active class to the current menu item.

        $rootScope.showDash = false;
        $rootScope.showCC = false;

        var location = $location.url().split('/');

        if(location[1] == 'customerCare'){
            $rootScope.showCC = true;
        }
        else if(location[1]=='dashboard'){
            $rootScope.showDash = true;
        }

        $rootScope.hasSubMenu = function(menuType){
            if(menuType=='dashboard'){
                $rootScope.showCC = false;
                $rootScope.showDash = $rootScope.showDash === false ? true: false;
            }
            else if(menuType=='customerCare'){
                $rootScope.showDash = false;
                $rootScope.showCC = $rootScope.showCC === false ? true: false;
            }
        }

By default $rootScope.showDash and $rootScope.showCC are set to false. It will set the menus to closed when page is initially loaded. If you have more than two submenus add accordingly.

hasSubMenu() function will work for toggling between the menus. I have added a small condition

if(location[1] == 'customerCare'){
                $rootScope.showCC = true;
            }
            else if(location[1]=='dashboard'){
                $rootScope.showDash = true;
            }

it will remain the submenu open after reloading the page according to selected menu item.

I have defined my pages like:

$routeProvider
        .when('/dasboard/loan', {
            controller: 'LoanController',
            templateUrl: './views/loan/view.html',
            controllerAs: 'vm'
        })

You can use isActive() function only if you have a single menu without submenu. You can modify the code according to your requirement. Hope this will help. Have a great day :)

Matthieu Cormier
  • 2,185
  • 1
  • 21
  • 32
0

Here's an example to use ngclick & ng-if directives.

Note: that ng-if removes the element from the DOM, but ng-hide just hides the display of the element.

<!-- <input type="checkbox" ng-model="hideShow" ng-init="hideShow = false"></input> -->

<input type = "button" value = "Add Book"ng-click="hideShow=(hideShow ? false : true)"> </input>
     <div ng-app = "mainApp" ng-controller = "bookController" ng-if="hideShow">
             Enter book name: <input type = "text" ng-model = "book.name"><br>
             Enter book category: <input type = "text" ng-model = "book.category"><br>
             Enter book price: <input type = "text" ng-model = "book.price"><br>
             Enter book author: <input type = "text" ng-model = "book.author"><br>


             You are entering book: {{book.bookDetails()}}
     </div>

    <script>
             var mainApp = angular.module("mainApp", []);

             mainApp.controller('bookController', function($scope) {
                $scope.book = {
                   name: "",
                   category: "",
                   price:"",
                   author: "",


                   bookDetails: function() {
                      var bookObject;
                      bookObject = $scope.book;
                      return "Book name: " + bookObject.name +  '\n' + "Book category: " + bookObject.category + "  \n" + "Book price: " + bookObject.price + "  \n" + "Book Author: " + bookObject.author;
                   }

                };
             });
    </script>
Abdallah Okasha
  • 1,879
  • 17
  • 20