Angular 2 upgradeNg1Component not working - unknown provider - angularjs

I'm trying to create a simple Angular 1 + 2 hybrid application in TypeScript using the component directive pattern as described here: https://angular.io/docs/ts/latest/guide/upgrade.html#!#using-angular-1-component-directives-from-angular-2-code
I got it working with the regular directive declaration, but I can't get it to work with the component directive.
Just to contextualize: I'm actually creating a new Angular 2 application, but I need a component that hasn't been converted yet, called Formly, so I'm thinking about using the Angular 1 version in the meantime.
The full code is here: https://plnkr.co/edit/J5rK48?p=preview
I created a component directive following the heroDetail sample on the guide:
export const tstv1 = {
template: `<a>Angular 1: {{value}}</a><br/>`,
controller: function($scope) {
$scope.value = 'Angular 1';
}
};
Then I tried to use it by upgrading the component:
const tstv1 = upgradeAdapter.upgradeNg1Component('tstv1')
However this throws an error:
[$injector:unpr] Unknown provider: tstv1DirectiveProvider <- tstv1Directive
http://errors.angularjs.org/1.5.0-rc.1/$injector/unpr?>p0=tstv1DirectiveProvider%20%3C-%20tstv1Directive
What am I doing wrong?
Also, the examples don't have a import statement for the component directive. Should I add it or not? I have tried both and it doesn't work either way. If there isn't a import, how would Angular know where to get the directive from?
I tried it like this:
import {tstv1} from 'src/tstv1/tstv1.component'
Like I said I got it working using a regular directive:
app.directive('tstv1directive', function() {
return {
restrict: 'E',
require: '?ngModel',
template: '<a>Inside directive: {{value}}</a>',
controller: function($scope) {
$scope.value = "Works!"
}
}
}))
and I can upgrade and use it just fine:
upgradeAdapter.upgradeNg1Component('tstv1directive')

see the working one: https://plnkr.co/edit/nAiqX2w4ENkYd6Z8db7M?p=preview
The way you 'create' the component directive was actually just create an object, you have to register it as a component.
see main.ts
app.component('tstv1', tstv1);
and you have to import the tstv1 object as well in main.ts
after that, just downgrade it like the one you did with the regular directive.

Related

Angular JS - Get the component controller instance manuallly

In Angular JS I would want to get a component controller instance manually, that ideally is achieved through the require binding in component. I have a requirement where in I am outside the Angular JS component environment and I cannot use require.
// Sample require binding
module.component('superHeros', {
template: `
<h2>
Super Heros Component
</h2>
`,
require: {
parentCtrl: '^heroList'
},
controller: superHerosControler
});
Though I thought this could be achieved with $injector of angular but does not seem to work (throws Unknown provider).
So I want to do this
require: {
parentCtrl: '^heroList'
}
like this this.requiredController = $injector.get(<componentName>);
I understand that this works perfectly for Services or factories. Is there a way to achieve this or a workaround that can essentially get me an component controller instance ?
Plunker here
Any help would be appreciated. Thanks

angular 1.5 component template webpack require() causes error

I'm using angular 1.5.3 with es6, webpack and jade templates.
Everything works as expected except for the component's templates.
This works
var cmpnt = {
template: '<div>test</div>'
}
This also works (when I manually create the html file)
var cmpnt = {
template: require('./component.html')
}
This does NOT work
var cmpnt = {
template: require('./component.jade')
}
In the browser console, I get
Error: [$injector:unpr] Unknown provider: localsProvider <- locals
The .jade file exists, and I'm using require('./template.jade') in many other places of the app without problems.
Any ideas? Any more info I can provide?
jade-loader returns a function. You cannot to pass that function to template, you must to invoke the function before pass it
var cmpnt = {
template: require('./component.jade')();
}
note the call of function after require

Globally register a directive in Angular

I am developing an Angular application. I need to add special behavior to all links. In AngularJS would just write a directive like this:
angular.module('whatever.module', []).directive('href', function() {
return {
restrict: 'A',
link: function($scope, $element, $attrs) {
// do stuff
}
};
});
In Angular I can write a directive like this:
#Directive({
selector: '[href]',
})
export class MyHrefDirective {
constructor() {
// whatever
}
}
But how can I tell the application to use that directive globally? I have a ton of views with links on them. Do I have to import it and specify it in the directives array in every of those components (which is A LOT)?
I tried injecting it to the bootstrap function like you're supposed to do with services to have one instance globally but that didn't work
My understanding is that you have to opt in to all custom directives at the component level. Only PLATFORM_DIRECTIVES are implicitly included (ngFor, ngIf etc.).
However, you can register your own custom directive as a PLATFORM_DIRECTIVE
import { provide, PLATFORM_DIRECTIVES } from '#angular/core';
bootstrap(RootCmp, [
provide(PLATFORM_DIRECTIVES, {useValue: YourCustomDirective, multi: true}),
]);
Here is an article that talks more about the process:
http://blog.thoughtram.io/angular2/2015/11/23/multi-providers-in-angular-2.html
EDIT:
I consider this less of a concern now since components are declared at the module level. This means a lot less repetition since you no longer have to declare child components at the individual component level.

Angularjs module loading error

I am trying to execute the simplest angular piece of code that is as follows. I have defined ng-app="budgetTracker" in the div tag. Whenever I try to execute the html, it gives me the following error:
Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.2.26/$injector/modulerr?p0=budgetTracker&p1=Eā€¦gleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.2.26%2Fangular.min.js%3A18%3A387)
Code:
(function() {
var app = angular.module("budgetTracker", []);
app.directive("categories", function(){
return {
//User Attribute directives for mixin behavior such as a tooltip, else mostly use element directives
//Directive definition object - a configuration that defines how a directive is going to behave
restrict: 'E', // we are declaring a new html element
templateUrl : 'js/templates/categories.html' // url of the template to be injected
};
});
});
Would anyone know why? I am pointing to the google cdn for angular and I am also including the app.js file in the head tag.
I guess you are missing to execute the function in which you have written module.
Change your app.js to
(function(){
var app = angular.module("budgetTracker", []);
app.directive("categories", function(){
return {
//User Attribute directives for mixin behavior such as a tooltip, else mostly use element directives
//Directive definition object - a configuration that defines how a directive is going to behave
restrict: 'E', // we are declaring a new html element
templateUrl : 'js/templates/categories.html' // url of the template to be injected
};
});
})();

AngularJS $routeProvider injection fails in directive

I am currently trying to get in touch with AngularJS. Since I plan to build a rather complex web application I searched for an alternative to the ngView/$routeProvider combination to be found in the ng docs as I find them quite dissatisfying for a complex application with several navigation levels.
So what I tried is to write a custom directive called ngRoute that could be used like this:
<div ng-route="users">
<div ng-route=":id"></div>
<div ng-route></div><!-- default -->
</div>
What I currently have is the following directive definition:
angular.module('app').directive('ngRoute', function($routeProvider) {
var getRoute = function($el) {
var parts = [];
var $curEl = $el;
while($curEl.length > 0) {
parts.unshift($curEl.attr('ng-route'));
$curEl = $curEl.parent().closest('*[ng-route]');
}
return parts.join('/');
}
var directiveDef = {
link: function(scope, $el, iAttrs, controller) {
var route = getRoute($el);
// Register route observer dependant on calculated route...
}
};
return directiveDef;
});
Unfortunately, I get an error due to the DI of the $routeProvider which I need for the registration of the route observation:
Error: Unknown provider: appProvider <- app <- ngRouteDirective
Did I miss something here? Also, feel free to critisize my approach (maybe someone already found a better solution for my problem).
Yeah, I'm not too clear about the approach but shouldn't the dependancy injection be:
angular.module('app')
.directive('ngRoute',['$routeProvider, function($routeProvider) {
// etc,etc...
};
]);
I ended up using the router of the angular-ui project (http://github.com/angular-ui/ui-router)
I find it to be quite satsifying
Unfortunately, I still have no clue why my DI did not work properly
I just ran into this as well using Angular version 1.2.7 (latest as of posting date).
Jumping over to ui-router is tempting but I thought I would offer a work around (albeit a little hacky) that I have working and is stable.
First set up routes as usual, but add $routeProvider to your application:
app.config(function($routeProvider) {
$routeProvider.
when('/a/route/here', {action:"someAction"}).
otherwise({redirectTo:'index'});
app.routeProvider = $routeProvider;
});
Then in the directive add additional routes as needed using:
app.routeProvider.when(...);
Angular adds the new routes and processes them fine when you navigate to them.

Resources