0

i am trying to figure how to use angularjs and even after some reading i still think i got it wrong.

i have some UI values that need to be loaded and some default behaviour for some buttons that i want to define.

i have used the following code:

var webAdmin = angular.module('webAdmin', ['ngRoute', 'ngResource'])
    .config([
        '$routeProvider', '$locationProvider', function($routeProvider, $locationProvider, dataStore) {
            $locationProvider.html5Mode(false);

            $routeProvider
                .when('/', { templateUrl: '/app/views/dashboard.html', controller: 'DashboardController' })
                .otherwise({ redirectTo: '/' });
        }
    ]) // end config
    .run([
        function() {


        }
    ]); // end run

webAdmin
    .controller('sidebarMenuController', function($scope, $element) {
        $scope.collapseSidebar = function() {
            $element.parent().parent().toggleClass('sidebar-collapsed');
        }

        var lis = $element[0].querySelectorAll('#main-menu > li.has-sub');
        for (var i = 0, l = lis.length; i < l; ++i) {
            var li = lis[i];
            var ul = angular.element(li.querySelector('ul'));
            var el = angular.element(li.querySelector('a'));
            el.bind('click', function(e) {
                angular.element(li).toggleClass('opened');
                ul.toggleClass('visible');
            });
        }
    });

as you can see, i applied the default buttons behaviour in the controller, but i got a feeling that is the wrong place for it, is it?

also, where would i load my UI values? the UI values are "global" (used within the app and many controllers should be able to access it.) for example, i plan to load the menu items dynamically (based on user permissions), where should i load them?

EDIT:

loading UI values: Either by using $resource or $http to load external json if its not clear from the code, i need a collapse button for the menu and similar functionality.

EDIT2: The HTML:

<div class="sidebar-menu" ng-controller="sidebarMenuController">
    <header class="logo-env">

        <!-- logo -->
        <div class="logo">
            <a href="#">
                <img src="/images/logo.png" alt="" width="160" height="50">
            </a>
        </div>

        <!-- logo collapse icon -->

        <div class="sidebar-collapse">
            <a href="#" ng-click="collapseSidebar()" class="sidebar-collapse-icon">
                <i class="fa fa-navicon"></i>
            </a>
        </div>

        <!-- open/close menu icon (do not remove if you want to enable menu on mobile devices) -->
        <div class="sidebar-mobile-menu visible-xs">
            <a href="#">
                <i class="fa fa-navicon"></i>
            </a>
        </div>

    </header>
    <ul id="main-menu">

        <li id="search">
            <input type="text" name="q" class="search-input" placeholder="Search...">
            <button type="button" ng-click="searchClick()"><i class="fa fa-search"></i></button>
        </li>

        <li class="has-sub">
            <a href="/"><i class="fa fa-bar-chart"></i><span>Reports</span></a>
            <ul>
                <li><a href="#"><i class="fa fa-bar-chart"></i><span>New Report</span></a></li>
                <li>
                    <a href="#"><i class="fa fa-folder-open"></i><span>Open Report</span></a>
                </li>
                <li>
                    <a href="#"><i class="fa fa-save"></i><span>Save Report</span></a>
                </li>
            </ul>
        </li>
    </ul>
    <div class="logo-vert hidden-xs"><a href="#"><img src="/images/logo.png"></a></div>
</div>

Plunker link as requested:

Plunker link

Rafael Herscovici
  • 16,558
  • 19
  • 65
  • 93
  • 1
    If you are using JQuery in Angular then you are most likely doing something wrong. What does your HTML look like that needs behavior on it? – Matthew Green Dec 01 '14 at 15:30
  • @MatthewGreen - i do not use JQuery (except JQuery light which is part of angular). also, i need help on where to implement the `$resource` call to get the initial values, so i am not asking for a review of my code, but to understand where to implement. – Rafael Herscovici Dec 01 '14 at 15:37
  • Sorry about that. The `$element` line looked like JQuery when I glanced over it. Also, you don't mention anything in your question about `$resource`. You may want to update your question with information about that. – Matthew Green Dec 01 '14 at 15:39
  • added at the end for reference (since im not sure which one would be the right one to use) – Rafael Herscovici Dec 01 '14 at 15:41
  • First, can you show your HTML? Second, is it possible that you use ng-class and ng-click to modify classes on click, as opposed to using .bind ? – SoluableNonagon Dec 01 '14 at 16:18
  • @Dementic For what it is worth, I wasn't entirely wrong about you using JQuery in your code. [See the doc for angular.element](https://docs.angularjs.org/api/ng/function/angular.element). – Matthew Green Dec 01 '14 at 16:56
  • @MatthewGreen - i think you missed the second part of that statement '. If jQuery is not available, angular.element delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite."' – Rafael Herscovici Dec 01 '14 at 17:55
  • @SoluableNonagon - yes, i do use `ng-click`, i am not sure of the correct way and `ng-click` seemed the right choice. unless you can tell me differently. as you can see in my code, i also used `bind` but am unsure if either is correct. – Rafael Herscovici Dec 01 '14 at 18:01
  • Can you provide a plunker of your code? http://plnkr.co/edit/ufjSYH7jhy7Gn64cFoHa here is a blank template to get you started – SoluableNonagon Dec 01 '14 at 18:18
  • Yeah, this needs to be done in a directive, with a directive you have the power to inject a service as well! So, a controller is just meant to delegate data to the view, a directive works more on the html rendering based on a particular model data. – Callum Linington Dec 02 '14 at 08:49

1 Answers1

1

Your code looks like you might start with this guide. Here are some pointers from me:

Adjusting View and Going Up the DOM Tree

When updating the view based on user interaction, you should almost never need to use the jQueryLite functions (outside definitions of your own directives). Additionally, to keep your code modular, you shouldn't walk up the DOM tree from your controller's $element. So, if you want to implement sidebar toggling, you'd go about it this way:

  1. define sidebar.isVisible on the outer scope (so that it is visible from the elements you need to adjust),
  2. use ng-show directive to show/hide the sidebar based on your variable, and

    <div class="sidebar" ng-show="sidebar.isVisible">...</div>
    
  3. change just the value of that variable from the inner scope.

    $scope.collapseSidebar = function () {
        $scope.sidebar.isVisible = false;
    };
    

Binding event handlers

When binding event handlers, do not use jQueryLite functions like .bind(), if you can help it. Not only do they call the handlers outside AngularJS $digest cycle (which means you need to call their code inside an $apply()), but they also lead to much less transparency in your code.

For example, when binding to click on your <a> elements, use simply

<a ng-click="someHandler()">...</a>

or

<a ng-click="someHandler($event)">...</a>

if you want to get the event data. Your handler should, again, just change some data on scope, not manually modify element classes, etc.

Loading and Storing Global Data

When loading data to be used across the whole application, you could simply do:

angular.module('...', [...]).run(['$http', '$rootScope', function ($http, $rootScope) {
    $http(...).success(function (data) {
        $rootScope.someDataVar = data;
    });
}]);

and see your data across all scopes. However, this pollutes your $rootScope needlessly. Instead, you could just create an outer controller encapsulating your whole view, and put the data on its scope. Additionally, you might want to store your global data in a global service, so that it can be injected into other services that aren't bound to any scope.

Community
  • 1
  • 1
hon2a
  • 7,006
  • 5
  • 41
  • 55