I am a rails developer new to angular js.
In MVC framework languages we can specify routes for an action or method in controller.
Is there any way to call a function of controller in angular js using angular ui-router
Well, you won't automatically fire a method by specifying correct routing, but you can manage it on your own, like this:
angular('app').config(function( $routeProvider ){
$routeProvider.when("/ctrl",
{
action: "ctrl.default"
}
);
});
angular('app').controller('ctrl', function($route) {
render = function() {
$scope.action = $route.current.action.split( "." );
}
$scope.$on("$routeChangeSuccess",function( $currentRoute, $previousRoute ){
render();
});
Basicly, event gets fired every time elements in route are changed, meanwhile in render() method you can work on case switching correct action for provided parameters in $scope.action
As you can see, the variable action is the one, which holds info that is passed to controller.
Above code is written without testing, so beware :p
Related
We're not using AngularJs as a SPA but embedded module to manage some behavior and shared data, so we're not actually utilising something like angular router. How should I initialize components only after a shared data service finished an asynchronous request? AngularJS was used with Typescript
Angular Module
import ... from '...'
import ... from '...'
...
angular.module('app-1', [])
.service('data-service', DataService)
.component('zeroDateButton', new ZeroDateButtonComponent())
.component('zeroPanel', new ZeroPanelComponent())
.component('zeroChart', new ZeroChartComponent())
ASP.NET Page hosting Angular module
BI.aspx
<asp:Content ID="standardContent" ContentPlaceHolderID="MainContent" runat="server">
...
<zero-date-button></zero-date-button>
<zero-date-button></zero-date-button>
<zero-panel name="panel-1"></zero-panel>
<zero-panel name="panel-2"></zero-panel>
<zero-panel name="panel-3"></zero-panel>
<zero-chart></zero-chart>
...
<script src="Scripts/Components/component.app-1.js) "></script> //compiled angular module js file
</asp:Content>
Page URL: https://www.example.com/BI/Zero
DataService.ts
public tryGetData() {
return $http.get(url).then((res: any) => {
this.panels = res.panels;
});
}
ZeroPanelComponent.ts
...
public $onInit(): void {
this.panels = this.dataService.panels;
this._render();
...
Most of the logics for this module relies on the data from the three components, so I want to fetch and store them all together in the data service, from which each component access the data they need from this service, and let the service figure out the logics and tell each of them by broadcasting the events.
Upon the components initialization(in $onInit method), it should display things using data retrieved from data service. The problem is component initialization is not awaiting data service to finish data fetching, so the component can't get the data they need and render nothing.
Trial with $routeProvider
I've seen seen lot's of people advising $routeProvider with appModule.config(), however it was not working. I'm not sure if this solution will work considering the way we use Angular, but I'm still posting the code snippet.
angular.module('app-1', ['ngRoute'])
.config(($routeProvider) => {
$routeProvider
.when('/BI/Zero', {
template: '<zero-panel class="flex-basis-half marginBottom" panel-name="SalesSnapshot", container-id="sales-snapshot"></zero-panel>',
resolve: {
DataService: (DataService) => {
return DataService.tryGetData();
},
},
});
})
.service('zero-data-service', DataService)
...
and I added ng-view directive to one in BI.aspx
There's NO error in browser, <zero-panel> is not rendered and tryGetDate() is not called too. I found someone said the 'path' defined to when() is part of the URL after the # symbol. Could you verify if this is true?
In terms other solution, the most intuitive thing I can think of is broadcasting an event when data service has obtained the data, and components listen to event to fetch the data, instead of fetching during their initialization.
I appreciate if anyone can suggest if $routeProvider would work in my usecase, or suggest any other possible solution to achieve the goal.
I have an old Angular1.5 app, quite a large code base.
I'm now using ngReact to instance React from within an angular directive.
This is all working correctly. My new react 'sub-app' for want of a better phrase is working ok.
But now I need to call an ng-click in part of the old Angular app from React. The Angular ng-click then pops up a modal. The ng-click in the controller is in scope so it's available i.e. it's module is loaded into the browser.
Any ideas how to do this ?
I do have Redux instanced in Angular using ngRedux and available in React, could I dispatch from React and get the controller to respond to this dispatch / action ?
Does this seem ok ?
The answer to my question is yes, I can use Redux and subscribe to the redux state change in the angular controller with something like this
var unsubscribeRedux = $ngRedux.connect(this.mapStateToThis, fireAddTaskEvent )(this);
$scope.$on('$destroy', unsubscribeRedux);
this.mapStateToThis = function(state) {
console.log("fired from react");
return {
value: state.addTasks
};
}
It's crude at the moment, but works
Right now I am using angular.element(document).ready(init()); but it calls init(); on every page refresh and not when browsing back and forth to the page. How could I call this function on every page view ?
I've tried also onload and ng-init and they don't work - the function doesn't get called.
I think this is what you're looking for:
$routeChangeSuccess Broadcasted after a route change has happened successfully. The resolve dependencies are now available in the
current.locals property.
ngView listens for the directive to instantiate the controller and
render the view.
This is what I do and it works for me:
$scope.$on('$routeChangeSuccess', function () {
// do something
});
Unless you're using ui-router. Then it's:
$scope.$on('$stateChangeSuccess', function () {
// do something
});
More info is found in the docs
I have a angularjs project that's using ui-router for routing.
I am using $state.reload() to reload the current state and it works just fine except that in my development system i want the $state.reload() to also reload the html template to reflect the new changes without a full page reload.
Is there a hack or option to do this ?
Update :
Chris T's solution almost worked, but i have templateFactoryDecorator witch adds a cache buster to the template url.
function configureTemplateFactory($provide) {
// Set a suffix outside the decorator function
var cacheBuster = Date.now().toString();
function templateFactoryDecorator($delegate) {
var fromUrl = angular.bind($delegate, $delegate.fromUrl);
$delegate.fromUrl = function (url, params) {
if (url !== null && angular.isDefined(url) && angular.isString(url)) {
url += (url.indexOf("?") === -1 ? "?" : "&");
url += "v=" + cacheBuster;
}
return fromUrl(url, params);
};
return $delegate;
}
$provide.decorator('$templateFactory', ['$delegate', templateFactoryDecorator]);
}
so
$templateCache.remove($state.current.templateUrl);
didn't work and i had to use
$templateCache.removeAll();
Its not ideal but for development environment its ok.
Internally, UI-Router leverages the $templateCache service to avoid re-fetching templates. Before calling $state.reload(), clear out the template you want to refetch from the server.
Assuming you want to do this from a controller:
function MyController($scope, $templateCache, $state) {
$scope.reload = function() {
$templateCache.remove("/path/to/template.html");
$state.reload();
}
}
Docs:
$templateCache
$cacheFactory
On a side note, I find it odd that you would want to refetch the template from the server.
I may have missed your point but When you use $state.reload() it reloads the state that means all the partials in side that template and the controllers in side that controller scope. Thus the state is reloaded not the full page.
So I see no errors in your side unless you want to do other staff ..
And if you are dynamically generating the DOM, It will do it for you .
In new angular components, $scope cannot be injected so I can't use the standard $emit.
How to I emit a value from a component to parent controller?
I have this in appCtrl:
$scope.$on('eventName', function (event, args) {
this.pageTitle = args.pageTitle;
}.bind(this));
Usually I have done it using:
this.scope.$emit('eventName', { pageTitle: _this.campaign.title });
I have a similar issue. I need to do a $scope.apply() in a component.
Check this issue here How can we watch expressions inside a controller in angular 1.4 using angular-new-router
I am not sure if using / injecting $scope into a component is the way to go because of the migraiton path to Angular 2. Maybe there is a better way using zone.js https://github.com/angular/zone.js/