I recently learned about Angular.js. Here I integrate Angular.js with Beego (Go Framework) to develop Single Page Application. I confuse how to automatically invoke method inside Angular controller?
Here's my angular controller:
angular.module('myApp')
.controller('BarangMasukController', ['$scope', '$http', 'myServices', function ($scope, $http, myServices) {
var initializeTask = function () {
myServices.testAPI()
.then(function (response) {
$scope.Sa = response.data.S;
$scope.Da = response.data.D;
console.log("Sa"+$scope.Sa);
console.log("Da"+$scope.Da);
});
}
initializeTask();
}]);
My angular service:
angular.module('myApp')
.factory('myServices', ['$http', function ($http) {
return {
//testapi
testAPI: function () {
return $http.get('/myapi');
},
};
}]);
my angular routes:
angular.module('myApp').config(function($routeProvider, $locationProvider) {
$routeProvider
.when("/testAPI", {
templateUrl: "static/views/penjualan/manage_penjualan.tpl",
controller: 'BarangMasukController'
})
.otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(true);
});
As you can see, I need to call method initializeTask() manually in my controller. The problem arise when there are multiple methods inside my controller. Please help.
If you want your methods to be automatically invoked, you can make use of Immediately Invoked Function Expression (IIFE) from JavaScript which is a function that runs as soon as it is defined.
(function () {
// logic here
})();
See the Mozilla developer guide for more info.
If you want to place all your initialization logics in a method and if you are using components then you can make use of angularjs $onInit() lifecycle hook which will automatically get invoked after all the controllers on an element have been constructed and had their bindings initialized. More info can be found here.
Related
I'm trying to test that some code gets executed using $scope.$on in an AngularJS 1.5+ component. I'm not sure how to set up the $rootScope correctly in Jasmine so I can execute the broadcast. I'm using this stackoverflow page and this blog as a reference. Here is my code.
// Component
(function (app) {
app.component('demoComponent', {
controller: ['$scope' function ($scope) {
$scope.$on('someBroadcast', function (data) {
// do something with data...
});
}]
});
})(angular.module('demoApp'));
// Jasmine setup
var ctrl, $rootScope, $componentController;
beforeEach(function () {
module('demoApp');
inject(function ($rootScope, _$componentController_) {
ctrl = $rootScope.$new();
$componentController = _$componentController_('demoComponent', { $scope: ctrl }, null);
});
});
My code breaks down in the inject function in the Jasmine setup. Does anyone know what I need to change to get this working?
Since ctrl is the scope that you will be using inside of your controller, you can do this:
ctrl.$broadcast('someBroadcast', 'test', 'values, 123);
And as a side note, usually you will name your scopes something like scope or $scope, or maybe event controllerScope. ctrl implies that the object is a controller, which it is not.
For some reason, the second Controller isn't receiving the data from the Service.
I'm trying to make the communication between two Controllers using one Service for it.
The View:
<div class="btn-wrapper" ng-controller="FirstController">
<a ng-href="" ng-click="doPath()" id="go" class="button">GO!</a>
</div>
The FirstController.js:
angular.module('app')
.controller('FirstController', function($scope, sharedService) {
$scope.doPath = sharedService.searchPath;
});
The sharedService:
angular.module('myServices', [])
.service('sharedService', function($rootScope) {
this.searchPath = function() {
console.log("I got the service!");
$rootScope.$broadcast('Search', {
data: 'something'
});
}
});
And the SecondController.js
angular.module('app')
.controller('SecondController', function(sharedService, $scope) {
$scope.$on('Search', function(event, data){
console.log(data);
//this.search(); => I intent to run this function after this
});
});
The event is dispatched by a button in the View, that calls the doPath() function. This function does communication with the Service sharedService and the message "I got the service" is displayed.
However, the app stops here. And the communication between Service and the second Controller, using $rootScope.$broadcast, seems that not happening (the data isn't showing on console, neither any error).
I found some solutions here. I have tried already all of answers, so the problem is not the same, cause still not working.
EDIT
The ngRoute is here (app.js):
angular.module('app', ['ngRoute', 'myServices'])
.config(function($routeProvider){
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'FirstController'
})
.otherwise({
redirectTo: '/'
});
});
As everyone suggested 'Instantiation' of the Second controller is needed.
<div ng-controller="firstController">
//code
</div>
<div ng-controller="secondController">
//code
</div>
Like above.
I know you have used 'ngRoute'. Until you change your view the second controller will not be loaded in 'ngRoute' whereas in above code both the controllers are in the same view. That is why above code works and 'ngRoute' does not.
SecondController is not instantiated by Angular because you are referring only FirstController from html. You need to instantiate the SecondController on the same html using parent child or sibling relationship depending on your application.
I have different views each created by a different controller. At a particular time only one of the views is visible.
I want to switch from one view to another view through a function of the controller of the first view and after that I want to call a method of the second view controller.
My problem is how should I call this method in an angular way?
I know the possiblity using $broadcast and $on but that smells a little bit.
The other choice ist to find the scope in the dom and calling the method via scope. But that is even more ugly.
What is the best solution?
You can use services to communicate between controllers. While you could create a generic shared service to have a central point to subscribe to and broadcast events, services are easier to maintain over time.
You can use Angular Routing
Check out the documentation. This is an excerpt from the documentation. You can make links like
Link
For the first route and so on.
phonecatApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'partials/phone-list.html',
controller: 'PhoneListCtrl'
}).
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: 'PhoneDetailCtrl'
}).
otherwise({
redirectTo: '/phones'
});
}]);
Okay it is done and simpler as expected.
The idea is to use a service used in both views (controllers), that contains a 'execution boolean'.
The first view set the boolean to true, the second set a watch on this boolean and therefore is called and can call the desired method.
In the service:
trigger: function(name) { model[name] = true; },
setTriggerWatch: function(scope, name, callback) {
scope.$watch(function value() {
return model[name];
}, function listener(newValue, oldValue) {
if (newValue) {
callback();
}
});
},
In the destination controller:
sessionData.setTriggerWatch($scope, 'createSession', function callCreateSession() {
_createSession();
});
In the source controller:
sessionData.trigger('createSession');
I'm trying to use ng-view inside a custom directive but it's not working and it's also not giving me any console error.
This is my directive:
(function() {
'use strict';
angular
.module('app')
.directive('header', Header);
Header.$inject = ['USER_AGENT'];
function Header(USER_AGENT) {
return {
restrict: 'A',
templateUrl: 'app/shared/header/header.html',
controller: controller
}
function controller($scope) {
$scope.isMobile = USER_AGENT.isMobile;
}
}
})();
And inside header.html file I have a call to ng-view just like I was calling it outside (when it was working).
Is it possible to nest ngView inside a custom directive?
AngularJS does not support multiple ng-views in one app. If you want it - you have to use another routing engine, for example Angular UI's ui-router
Even if you could use it you shouldn't because is not the correct approach for Angular a directive should be treated like a web component like input, select, etc.
Just remember that your header.html is just a view and can be used by pretty much anything, is just the view
.directive('myDirective', function($timeout) {
return {
restrict: 'A',
templateUrl: 'app/shared/header/header.html',
controller: controller
});
Or (using ui-router)
$stateProvider
.state('home', {
url: '/?accountkey',
templateUrl: 'app/shared/header/header.html',
controller: controller
});
I have added some logic for authentication in my angular app and the initial the call to the service wrapping the webapi is executed in the app.run function, like this:
myApp.run(function ($rootScope, $location, myService) {
myService.getCurrentUser().then(function (promise) {
//reroute to either access denied or the start page when access is verified.
});
// register listener to watch route changes
$rootScope.$on("$routeChangeStart", function (event, next, current) {
//check access
});
});
After this all my unit tests broke, since I don't know how to inject the mocked version of myService before creating the app module. I've factored out the service and the mocked service in a seperate module so I can create it before creating the actual app. Like this:
angular.mock.module('ServiceModule');
angular.mock.module('EArkivApp', function ($provide, myMockedService) {
$provide.value('myService', myMockedService);
});
This is not working however, it complains that "myMockedService" (which is part of the ServiceModule) is an unkown provider. Do you have any good suggestions of how I should solve this?
Could you provide us for a jsfiddle?
Meanwhile, if you are using Karma then you can use something like this:
/*global describe, beforeEach, module, inject, it, expect*/
describe('Controller: MyCtrl', function () {
'use strict';
// load the controller's module
beforeEach(module('myApp'));
var MyCtrl,
scope,
modalInstance;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope, myMockedService) {
scope = $rootScope.$new();
modalInstance = _$modal_.open({
templateUrl: 'views/my-template.html'
});
MyCtrl = $controller('MyCtrl', {
$scope: scope,
$myMockedService: myMockedService
});
}));
it('should be true', function () {
expect(true).toBe(true);
});
});
I learned this by using Yeoman scaffolding, by the way :)