How to refer to a template by id in angular2? - javascript

I'm trying to find a way to refer to a file by using an unique name instead of a folder path. With absolute and relative path, if I move the components folder I have to refactor all the link. That is quite annoying also because by using gulp all the javascript file are moved to another directory.
In Angular 1 we just refer to the ID of the ng-template.
Is there a way to do a similar thing in Angular 2?
Additional information:
Code I'm currently using
(function(app) {
app.AppComponent =
ng.core.Component({
selector: 'my-app-test',
templateUrl: '/assets/base/components/comp-test-app/test-template.html'
})
.Class({
constructor: function() {}
});
})(window.app || (window.app = {}));

You can reference the template by relative urls by setting the moduleId of the component.
(function(app) {
app.AppComponent =
ng.core.Component({
moduleId: module.id,
selector: 'my-app-test',
templateUrl: 'test-template.html'
})
.Class({
constructor: function() {}
});
})(window.app || (window.app = {}));
Source: https://angular.io/docs/ts/latest/cookbook/component-relative-paths.html

Related

sending variable from index.html to app.component.ts

Can i send a variable from index.html to app.component.ts
i have this script in index.html and i want to send url which is variable before removing query params to app.component.ts
<script type="text/javascript">
var url = window.location.toString();
if(url.indexOf("?") > 0) {
var sanitizedUrl = url.substring(0, url.indexOf("?"));
window.history.replaceState({}, document.title, sanitizedUrl);
}
</script>
Of course you can. I made a small demo to show you how.
All you have to do is wrap your code as you did in index.html.
You have to declare the variable. You can do it inside the component as
import { Component } from '#angular/core';
// notice that foo is inited in index.html
declare var foo;
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
or in typings.d.ts. I recommend declaring it in typings.d.ts. If you're using angular-cli, and i assume, it is located in src/app/typings.d.ts.
declare var foo: any;
And that's it. You can use your variable anywhere in the app.
Inside .html file -->
<script>
const baseUrl = "http://0.0.0.0/";
</script>
in .ts file just declare the variable and use it -->
declare var baseUrl;
export const BASE_URL = baseUrl;

Angular 5 with es5

Angular 4 supports below syntax
var HelloComponent = ng.core
Component({
selector: 'hello-cmp',
template: 'Hello World!',
viewProviders: [Service]
.Class({
constructor: [Service, function (service) {
},`
});
In Angular 5 , Class is missing anyone can provide Angular 5 with ES5 syntax currently
i am not able to switch ES6 so please avoid that suggestion.
if switching to ES6 is the only way then i will stick to angular 4 as of now
You need to use static properties annotations and parameters on your component class function something like this:
function Service() {}
function AppComponent(service) {
console.log(service);
}
AppComponent.prototype.ngOnInit = function() {
console.log('test ngOnInit');
};
AppComponent.annotations = [
new Component({
selector: 'my-app',
template: '<h1>Example of Angular 5.0.5 in ES5</h1>',
viewProviders: [Service]
})
];
AppComponent.parameters = [ Service ];
Plunker Example

Angular 2 custom directive with es5

I'm trying to build a custom directive / Angular 2 using vanilla es5.
Here is the code
(function(app) {
app.CustomDirective = ng.core.
Directive({
selector: 'test',
})
.Class({
constructor: function CustomDirective() {
console.log('ds')
},
ngOnInit: function() {
}
});
})(window.app || (window.app = {}));
I declare it into the ngmodule
(function(app) {
app.AppModule =
ng.core.NgModule({
imports: [ ng.platformBrowser.BrowserModule, ng.http.HttpModule ],
declarations: [ app.AppComponent, app.CustomDirective],
providers: [app.MyService ],
bootstrap: [ app.AppComponent ]
})
.Class({
constructor: function() {}
});
})(window.app || (window.app = {}));
in The AppComponent
(function(app) {
app.AppComponent = ng.core.
Component({
selector: 'my-app',
templateUrl: '//app/app.component.html',
directives: [app. CustomDirective ]
})
.Class({
constructor: [app.MyService, function AppComponent(myService) {
this.myService = myService;
}],
ngOnInit: function() {
}
});
})(window.app || (window.app = {}));
and in the html
<h2 test >Test</h2>
But the console log i have in the constructor of the directive never gets fired.
If i declare it instead of the declarations array, to the providers array it gets called which is odd since it's a directive and because of that I can't access the elementRef for the element I apply the directive.
I'm using the latest angular 2 version as is in the package.json form the quickstart guide
UPDATE:
I need to update this line
Directive({
selector: 'test',
})
to this
Directive({
selector: '[test]',
})

trying to internationalize title and description of an adf-widget in Angular (Blur Admin)

is it possible to translate title and description of an adf-wiget?
i've tried something like this, but it did not work:
angular.module('adf.widget.myWidget', ['adf.provider'])
.config(function(dashboardProvider, $filter){
dashboardProvider
.widget('myWidget', {
title: $filter('translate')('MYWIDGET.NAME'),
description: $filter('translate')('MYWIDGET.DESCRIPTION'),
templateUrl: '{widgetsPath}/myWidget/src/view.html',
controller: 'myWidgetCtrl',
edit: {
templateUrl: '{widgetsPath}/myWidget/src/edit.html'
}
});
})
.Controller [...]
or is there a way to update those informations in a controller using the $filter?
Thanks a lot
// EDIT:
I've tried an other solution, but it still wont work:
angular.module('adf.widget.myWidget', ['adf.provider'])
.config(function(dashboardProvider){
function getName($filter) { var dcName = $filter('translate')('MYWIDGET.NAME'); return dcName; };
dashboardProvider
.widget('myWidget', {
title: getName(),
description: 'test',
templateUrl: '{widgetsPath}/myWidget/src/view.html',
controller: 'myWidgetCtrl',
edit: {
templateUrl: '{widgetsPath}/myWidget/src/edit.html'
}
});
})
Here is an example of how to use the resolve block
angular.module('adf.widget.myWidget', ['adf.provider'])
.config(function(dashboardProvider, MYWIDGET){
dashboardProvider
.widget('myWidget', {
templateUrl: '{widgetsPath}/myWidget/src/view.html',
controller: 'myWidgetCtrl',
edit: {
templateUrl: '{widgetsPath}/myWidget/src/edit.html'
},
resolve: {
description: function ($filter) {
return $filter('translate')(MYWIDGET.DESCRIPTION)
},
name : function ($filter) {
return $filter('translate')(MYWIDGET.NAME)
}
}
});
})
Then in your controller myWidgetCtrl, inject in the translated name and description values as normal injectables
MYWIDGET should be defined as a constant with values for its NAME and DESCRIPTION properties and then injected into the config block, just the way you injected $filter
Take a look at angular module system to see how to create constants
I solved this issue by translating the values in custom templates.
dashboardProvider.customWidgetTemplatePath('src/...pathToTemplate')
I'am also using custom templates for all edit-templates like editTemplateUrl etc.
(Deleted the duplicated question..)

AngularJS ui-router: how to resolve typical data globally for all routes?

I have an AngularJS service which communicates with the server and returns
translations of different sections of the application:
angular
.module('utils')
.service('Translations', ['$q','$http',function($q, $http) {
translationsService = {
get: function(section) {
if (!promise) {
var q = $q.defer();
promise = $http
.get(
'/api/translations',
{
section: section
})
.success(function(data,status,headers,config) {
q.resolve(result.data);
})
.error(function(data,status,headers,config){
q.reject(status);
});
return q.promise;
}
}
};
return translationsService;
}]);
The name of the section is passed as the section parameter of the get function.
I'm using AngularJS ui-router module and following design pattern described here
So I have the following states config:
angular.module('app')
.config(['$stateProvider', function($stateProvider) {
$stateProvider
.state('users', {
url: '/users',
resolve: {
translations: ['Translations',
function(Translations) {
return Translations.get('users');
}
]
},
templateUrl: '/app/users/list.html',
controller: 'usersController',
controllerAs: 'vm'
})
.state('shifts', {
url: '/shifts',
resolve: {
translations: ['Translations',
function(Translations) {
return Translations.get('shifts');
}
]
},
templateUrl: '/app/shifts/list.html',
controller: 'shiftsController',
controllerAs: 'vm'
})
This works fine but as you may notice I have to explicitly specify translations in the resolve parameter. I think that's not good enough as this duplicates the logic.
Is there any way to resolve translations globally and avoid the code duplicates. I mean some kind of middleware.
I was thinking about listening for the $stateChangeStart, then get translations specific to the new state and bind them to controllers, but I have not found the way to do it.
Any advice will be appreciated greatly.
Important note:
In my case the resolved translations object must contain the translations data, not service/factory/whatever.
Kind regards.
Let me show you my approach. There is a working plunker
Let's have a translation.json like this:
{
"home" : "trans for home",
"parent" : "trans for parent",
"parent.child" : "trans for child"
}
Now, let's introduce the super parent state root
$stateProvider
.state('root', {
abstract: true,
template: '<div ui-view=""></div>',
resolve: ['Translations'
, function(Translations){return Translations.loadAll();}]
});
This super root state is not having any url (not effecting any child url). Now, we will silently inject that into every state:
$stateProvider
.state('home', {
parent: 'root',
url: "/home",
templateUrl: 'tpl.html',
})
.state('parent', {
parent: 'root',
url: "/parent",
templateUrl: 'tpl.html',
})
As we can see, we use setting parent - and do not effect/extend the original state name.
The root state is loading the translations at one shot via new method loadAll():
.service('Translations', ['$http'
,function($http) {
translationsService = {
data : {},
loadAll : function(){
return $http
.get("translations.json")
.then(function(response){
this.data = response.data;
return this.data;
})
},
get: function(section) {
return data[section];
}
};
return translationsService;
}])
We do not need $q at all. Our super root state just resolves that once... via $http and loadAll() method. All these are now loaded, and we can even place that service into $rootScope:
.run(['$rootScope', '$state', '$stateParams', 'Translations',
function ($rootScope, $state, $stateParams, Translations) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$rootScope.Translations = Translations;
}])
And we can access it anyhwere like this:
<h5>Translation</h5>
<pre>{{Translations.get($state.current.name) | json}}</pre>
Wow... that is solution profiting almost from each feature coming with UI-Router... I'd say. All loaded once. All inherited because of $rootScope and view inheritance... all available in any child state...
Check that all here.
Though this is a very old question, I'd like to post solution which I'm using now. Hope it will help somebody in the future.
After using some different approaches I came up with a beautiful angularjs pattern by John Papa
He suggest using a special service routerHelperProvider and configure states as a regular JS object. I'm not going to copy-paste the entire provider here. See the link above for details. But I'm going to show how I solved my problem by the means of that service.
Here is the part of code of that provider which takes the JS object and transforms it to the states configuration:
function configureStates(states, otherwisePath) {
states.forEach(function(state) {
$stateProvider.state(state.state, state.config);
});
I transformed it as follows:
function configureStates(states, otherwisePath) {
states.forEach(function(state) {
var resolveAlways = {
translations: ['Translations', function(Translations) {
if (state.translationCategory) {
return Translations.get(state.translationCategory);
} else {
return {};
}
}],
};
state.config.resolve =
angular.extend(state.config.resolve || {}, resolveAlways || {});
$stateProvider.state(state.state, state.config);
});
});
And my route configuration object now looks as follows:
{
state: ‘users’,
translationsCategory: ‘users’,
config: {
controller: ‘usersController’
controllerAs: ‘vm’,
url: ‘/users’.
templateUrl: ‘users.html'
}
So what I did:
I implemented the resolveAlways object which takes the custom translationsCategory property, injects the Translations service and resolves the necessary data. Now no need to do it everytime.

Categories