Implement a logical part as Generic one in AngularsJs - javascript

I have recently started working on ANGULARJS in which I was encountered a case where I need some guidance to go through. Am implementing a message section in my application(ASP NET MVC - ANGULARJS).Currently I have implemented the message section for a specific module under a particular ng-app and under particular ng-controller. Now I need the same functionality to be used inside another module. It's like duplicating the same code again that ng-app under that ng-controller which was not a good approach. I just wanted like and plug and play kind of approach for my ANGULARJS code.
I have used 2 service,1 directive under that particular ng-app and some functions inside a particular controller. All I want is to make these one a common code and to be used inside under any ng-app and ng-controller.
Is this possible? If so how can I achieve.
Let me know if the query was unclear

You said you used 2 service, 1 directive, and controller etc for your messaging feature. If you want to re-use it across various applications, you need to bundle all of this as a module. for example:
angular.module('customMessaging', [])
.controller('messagingCtrl', function(messenger, messageManager) {
....
})
.directive('messagingDir', function() {
return {
controller: 'messagingCtrl'
...
}
})
.service('messenger', function() {
...
})
.service('messageManager', function() {
...
})
Now you can specify this as a dependency of any of your angular applications as shown below to access the directive, services and controller anywhere in the app:
angular.module('myfirstApp', ['customMessaging']);
angular.module('mySecondApp', ['customMessaging']);

Thanks for the suggestions. I have moved the message related functions such as services, directive and controller related functions into separate JavaScript file . And invoked this JavaScript file where I need message related functionalities.
Let us say that JS as Message.JS . In Message.JS I have used the app variable(Instantiated app from the JS Specific to the page globally).
JS specific to that page
var app = angular.module('appname',[]);
app.controller(...)
Message.JS
I have used the same app in my message.JS since message controller falls under that app.
app.service(...)
app.controller('messagecontroller',[]...)
When ever I need to invoke a function inside MessageController I will use Broadcast in angular to achieve this.For more info http://www.dotnet-tricks.com/Tutorial/angularjs/HM0L291214-Understanding-$emit,-$broadcast-and-$on-in-AngularJS.html
Regards,
Selvam.M

Related

ng-app or angular.bootstrap

I was thinking when it would be best to not use the ng-App directive and instead go for angular.bootstrap. I understand from documentation what ng-App directive does and how it helps in telling compiler to set root of compilation. So my question is as to why I should use angular.bootstrap? What do they mean by saying in documentation that "If you need to have more control over the initialization process, you can use a manual bootstrapping method instead" documentation. Then I would also like to know as to for the solution that I am thinking for my application. I have one index.html file with one ng-app directive. Now for my application, I have different APIs, lets say for admin, students and instructors. So this is what I was thinking.Have the following files:
index.html
admin.js
students.js
instructors.js
I will have controllers for all of them and separate moduels, which will get the data from those APIs. Each div that will display the data from those controllers will be associated with the specific module, using angular.bootstrap and index.html will not have the ng-App directive. Is this the right approach ? Should I be just using ng-App and multiple controllers and a single module? Any help in understanding this is appreciated. Thank You.
One guideline that might help you is that you can only use ng-app once, but you can use angular.bootstrap multiple times
"If you need to have more control over the initialization process, you can use a manual bootstrapping method instead"
This means that with ng-app whenever directive is encountered bootstrapping will start automatically.
But with manual bootstrapping we can control it, say we want some data to be loaded first, to check for something defined or not or even as normally we do with checking of DOM ready event.

Can I link an external javascript file to an AngularJS controller?

This may be a dumb question. I know AngularJS controllers use javascript code to keep the application logic outside of the view. But I was wondering if I could link an external javascript file to a controller so it didn't have to be so long.
If it is possible would you also share the syntax of how I would do this. Something like:
app.controller('demoCtrl', ['$scope', function ($scope) {
$scope.msgtxt='Hello World';
src=somejavascriptfile.js;
}]);
If your issue is that the controller logic is too long, you are correct that it is a code smell. You want to make the controller as thin as possible, just enough logic to handle the view events and updating the model (scope). If you want to refactor your controller code, the first step is to extract out the logic into service(s) (in angular lingo providers / factories / services). The services can then be injected into your controller, similar to how you have injected the $scope service.
Read this sitepoint article for details on how to do this.
The next step might be look for logic (mainly UI related) which can extracted into directives.
In case you need to use an external javascript library within your angular application, the optimal way is to add that script to the scripts section of your html file, and wrap the functionality in a service or a directive (if it is UI related). Make sure to check if there are angular modules available out there for the 3rd party library you want to pull in.
Not only you can split your controller code among different files, but you probably should do that. An angular controller is responsible for the business logic behind a view, and only for that. You are doing it wrong if, inside the controller, you are (list not exhaustive) :
accessing your backend from it
manipulating the DOM
writing utility code for showing alerts in your application (for example)
Your components should be concise and of a single responsibility.
Here follows an example of how you would export some part of your code in a service. You do not link a js file from a controller, but you load it in your page, and inject the service as an argument of your controller :
1) Load your service in index.html :
<script src="js/factories/loggerService.js"></script>
2) Implement your service in loggerService.js
app.factories('loggerService', function () {
//
// Implement here some logging methods
//
// IMPORTANT: do not bloat this service with methods not related
// with logging
//
});
3) Inject your service in your controller :
app.controller('demoCtrl', function ($scope, loggerService) {
loggerService.info(...)
});
By the way, this loggerService would be useful only if you need something different than the service provided by angular built-in service $log
In a different file, define a service containing the logic and just call it from the controller.
app.controller('demoCtrl', ['$scope', function (ServiceFromDifferentFile, $scope) {
$scope.msgtxt='Hello World';
ServiceFromDifferentFile.doStuff()
}]);

bootstrap AngularJS service with asynchronous data using angularAMD

I have a problem pretty much similar than the issue exposed in this question (AngularJS : Initialize service with asynchronous data). My difference is that I'm using angularAMD to load scripts asynchronously and I just can't fit the approaches above in the following app.config:
define(['angularAMD'], function (angularAMD) {
var app = angular.module('app', []);
app.config(['$routeProvider', function ($routeProvider) {
// some code here
}]);
app.run(['srvRules', function (srvRules) {
srvRules.getRules().then(function (result) {
// I need to bootstrap only after I get the rules from the server
});
}]);
return angularAMD.bootstrap(app);
});
EDIT 1
This is the approach I'm trying to accomplish: https://stackoverflow.com/a/21189057/2407203
EDIT 2
Adding more information: I have a webapi as the backend, it is a legacy system which provides all kinds of business rules needed to set up the application. The main information provided at this moment are:
I use $translateProvider(http://angular-translate.github.io) to dinamically load the dictionary with the current culture. All the texts should be taken from this dictionary.
I have a service that monitors all route changes and allows or restricts the access based on the rules returned.
Some information should be placed on the screen based on the rules. Those information are all encapsuled inside a directive on the initial html.
Some html controls may appear or not based on the rules as well.
There's really no easy or elegant way out. I ended up doing the following:
Started using ui-router(https://github.com/angular-ui/ui-router) instead of ngRoute;
Created a root abstract state, parent of all other states;
Used the resolve section of the root state to load all data needed before any controller get instantiated

Correct paradigm for mixing angular code with external code

Angular Newbie here. I'm trying to understand the paradigm to use when developing an Angular app so I can use external libraries while keeping the Angular app reusable.
So imagine I've got a form that uses ng-submit:
<form ng-submit="submit()">...<!--code goes here --></form>
And then inside the corresponding ng-app and ng-controller (assume those are declared in a parent element), I've got my submit function. But say, on this page only, I want to use a custom alert library after submitting:
$scope.submit = function(){
// code goes here to submit form data
//now tell the user that save was successful
customAlertLibrary.alert("your data has been saved")
}
Now that's not reusable code, is it? I may want to reuse this ng-app on another page to modify and submit data, but don't want to use the custom alert library. It seems like you're trapped because the ng-submit attribute restricts you to functions inside the corresponding ng-app, not external functions. So what is the correct way to invoke other Javascript code alongside my Angular code without baking it into the model?
This question is very similar to this question about making lodash available in templates. There are many ways of adding external (or in-app) code or data-structures to your Angular scope. I prefer to add special-purpose stuff to each scope individually, and general-purpose utilities (such as lodash or momentjs) globally:
app
.run(['$rootScope', function($rootScope) {
$rootScope._ = _;
$rootScope.moment= moment;
// or:
// $rootScope.util = {
// _: _,
// moment: moment
// };
});
If customAlertLibrary isn't crucial to your app, I'd say do something like this
$scope.submit = function(){
// code goes here to submit form data
//now tell the user that save was successful
if ($window.customAlertLibrary) {
customAlertLibrary.alert("your data has been saved");
}
}
Otherwise, I'd suggest using Bower to manage dependencies. You install packages with Bower, and your own app can be a package that gets included and installed by other apps. Any dependency your app has gets installed as well (the user still has to include it on their own end in a <script> tag)

Why ng-app not ng-module?

I understand that ng-app initializes a module in AngularJS as follows:
var app = angular.module('myApp', []);
<html ng-app="myApp">
But when I teach this to someone new to AngularJS or watch a video, instructors inevitable fumble over the inconsistency in the terminology between app and module. AngularJS is so well thought out as a framework that I'm surprised it hasn't changed to:
var app = angular.app('myApp', []);
<html ng-app="myApp">
OR
var app = angular.module('myModule', []);
<html ng-module="myModule">
Has anyone been following the project long enough to know the history on this part of the framework?
I don't think Craig is asking what does ng-app do or how does it work.
I think he's asking why did the people that created angular name that directive ng-app. Why didn't they name it ng-module. ng-module would be easier to understand.
For example ng-controller should name a controller, ng-module should name a module. The angular methods to create them are named module() and controller(), there is no method or entity called "app".
I tend to agree with Craig. That said if I were go speculate why they named it ng-app I would think it's because you are only allowed to have one ng-app directive in your HTML. If you wanted to have more than one module associated with your HTML page you can do it programmatically.
So ng-app is more of a utility to bootstrap your HTML with a module, it is not a generic way to associate modules with your HTML.
If you look at the documentation that's what it suggests:
Use this directive to auto-bootstrap an AngularJS application. The
ngApp directive designates the root element of the application and is
typically placed near the root element of the page - e.g. on the
or tags.
Only one AngularJS application can be auto-bootstrapped per HTML
document. The first ngApp found in the document will be used to define
the root element to auto-bootstrap as an application. To run multiple
applications in an HTML document you must manually bootstrap them
using angular.bootstrap instead. AngularJS applications cannot be
nested within each other.
http://docs.angularjs.org/api/ng/directive/ngApp
All that said if you want an ng-module directive you could always write your own to wrap the angular.bootstrap() function. You can find more details and code about how to do this on a blog post I wrote about it: AngularJS: Getting around ngApp limitations with ngModule
ng-app means: That page has Angular in it!
ng-app="module" means: That page has Angular in it and necessary controls/services/etc are defined in that module.
ng-app defines the main or bootstrap module of your application, which should perform the initialization task of your application. There may be case where at run time you want to decide what which should be the main module of your application. Like in java you have many methods and classes but you define one main method as starting point. Similarly, in angular you have many module, however, you define one module as the starting point of application.

Categories

Resources