Using AngularJS $apply to call functions across different controllers within same module

Intro.

If you read my old post about Splitting Application Page into Separate AngularJS MINI Components , you might need to also read this post as i am talking here about a way to call a controller function from different $scope using the $apply module (Digest Loading).

Why we might need this?

This is important when we are inside a $scope of controller of a directive or what ever and we need to call or execute another controller $scope function to get or post or what ever the function does.

Indeed you can use the AngularJS $rootscope but all am doing here is introducing another solution.

How to do it ?

Lets assume that we have two different Controllers assigned to two different Directives and two different modules, and from the first Controller ($scope) we need to call function inside second Controller ($scope).

In real case, this could be a “Menu Controller Btn.” toggles “Body Controller Div” Visibility  or what ever you might need.

This is a way to access another $scope functionality without changing the $scope.

First, assuming that the external $scope that we need to call a function inside is assigned to HTML Div or whatever with Class or Id, we need this to get the element assigned $scope by element ID or Class Name.

Note that all the following code snippets should be inside the first controller not the one the function implemented inside.

var externalScope = angular.element($("#comp-body")).scope();

I assumed here that we have an HTML Element with Id = comp-body and this element Controller is the one we seek its functions.

Then lets call the function inside this scope as if we are inside it

externalScope.$apply(function () {
 externalScope.doSomething();
});

Note that, doSomething should be in externalScope ($scope) or implemented this way:

$scope.doSomething = function()
{
//What ever ...
};

Important Note

In some cases you might need to add the last code snippet inside

$timeout(function () {
//put the $apply code here ...
});

to make sure you are not conflicting with same $scope in progress process.

 

Thanks,

Advertisements

Splitting Application Page into Separate AngularJS MINI Components

Intro.

In glance, and over decades of building many Web Applications, i can say that we are the lucky generation who has the opportunity to witness the “Rapid Evolution” of the front end development. And am not here to utilize this post for talking about the historical road map or even to judge any of these many sprints, am only giving a modern “Technologically Oriented” technique to build a (Smarter, Easier to Maintain, Better for re usability) and Firm Web Application page using AngularJS 1.x.

Case Study

I need to build an application page(s) with several parts and to provide a smart stable way to communicate between these parts and indeed to reuse them in other pages.

Assumption

I will assume that you have enough experience with AngularJS and good understanding to the basic AngularJS Definitions like (Module, Directive, Service, Controller and Template). and Upon this assumption i just guide you to use these framework in way to provide the Titled “Split Your Application Page Into MINI Components”.

Step 1: Conceptually Split Your Page to as MINI Components as you can.

I remember that I’ve worked in application and i created a component for a “Button” and i handled the Hover, Click, In Progress behavior all inside this Directive.

This Step is very important but don’t spend a lot in as it is kind of recursive phase to keep updating and split more or merge according to how work goes.

I will give you a hint of some elementary concepts to take care while splitting the page into Components:

  1. Define the Globally Shared Parts (e.g. Header, Footer, Menu, …etc).
  2. Define the Partially Shared Parts (e.g. Profile Picture in account management Pages)
  3. Define or Draw the different page parts Dependency and Communication (In/Out) (e.g. A Btn. on the header can Toggle Page body contents visibility, or like Filter changes should update results).
  4. Avoid Over Splitting that will add useless effort to integrate and inject.

and overall, stop we you feel you are about to loose the Orchestration between all page parts.

Step 2: Build The Solution Structure 

There are several opinions regarding this part and different schools, and i can’t tell you whats better but you have to always know that whatever concept you will implement, you will sacrifice the strength of the other one. I will show here two different ways and indeed you can scout over another.

The Functional Structure people here separate the components by function, it means every component with separate functionality be in a separate folder contains all of its artifacts (e.g. JS, HTML, LESS or CSS), and also the sub components.

pic-1

Pic 1 : The Functional Structure

The File Type Structure This one is not business or functional oriented as mush as it is a development structure, where you are grouping the same File Type artifacts in the same Folder, and you use the file name to refer to the function related to.

pic-2

Pic 2:The File Type Structure

You are the best to define the need to pick any or merge between them to define your own structure, but you always should consider some elements to decide based upon, like

  1. How you will bundle the application , as the File Type is mush easier that the Functional one in terms of bundling .
  2. Minification Scripts.
  3. Template Mapping and Template Path Security configurations.

Step 3: Build the Globally Shared Components First then Page Specific Components.

Because 99% of the Globally Shared components are the most simple components and the less dependent on other parts, so you better start with to build and define your framework first and firmly continue injecting further components.

Sample Component Implementation (Building Header Component)

Define the Component module to use later in Parent Module injection.

angular.module('comp-header', [])

Assign the Component Directive pointing to the Component Template.

angular.module('comp-header', []).directive('compHeader', function () {
return {
        templateUrl: 'components/header/template.html' 
       };
});

Create the directive Controller

angular.module('fcomp-header').controller('CompHeader',
['$scope', '$element', '$timeout',
function ($scope, $element, $timeout,) {

angular.element(document).ready(function () {
    //Write Down The Directive Start Up Logic Here
});
}]);

Build The Component Template (HTML) and assign the created Controller to

< div class="comp-header" ng-controller="CompHeader">
Write Down Your HTML here ...
< /div>

Inject the Created component to the Page Module

angular.module('home-page', ['ngRoute', 'ui.bootstrap', 'ngAnimate', 'comp-header']);
angular.module('home-page');

Finally : Use the components in the home page

< div id="CompHeader">< /div>

Now, You should be able to move on with the rest of your components and keep injecting in the Page of interest.

Further to read in same context:
1. Using Angular $apply to call functions across different controllers within same module.
2. Using Angular $sceDelegateProvider to add the Directive Template URL to the Module White List.