Angular Ng1/Ng2 hybrid app throwing 'No provider for $scope' exception - angularjs

I'm trying to build an hybrid Ng1/Ng2 app with NgUpgrade as an intermediate step in a migration towards Angular 2.
The bootstrap seems to work:
platformBrowserDynamic().bootstrapModule(AppModule).then( () => {
adapter.bootstrap(document.body, [Ng1AppModule.name]);
});
But I'm struggling at using a simple Ng1 directive in an Ng2 component, see this very simple plunker: https://plnkr.co/edit/gMSwKKIgEkwcijCCaCMW?p=preview
Even after having upgraded the Ng1 directive and downgraded the Ng2 component, the browser sends a "No provider for $scope!" exception.
What have I missed ?
I know that some people have already reported this exception, but it looks like NgUpgrade has evolved a lot since the beta of Angular 2, and I can't find the appropriate answer for current Angular 2 release.

Found it !
My mistake was to try to bootstrap directly a ng2 module, but it looks like you have to put a ng1 component at top level of the DOM (yes it's written somewhere in the official ngUpgrade guide). Here is the correct updated plunker with a ng1 root component, that calls a ng2 module, that calls another ng1 component.
const myNg1Root = {
template: `
<p>This is the Angular 1 root component</p>
<ng2root></ng2root>
`,
};

Related

Hybrid AngularJS/Angular 6 app module dependency issues

I'm currently exploring an upgrade path for a pretty large AngularJS 1.6 app to Angular 6. I have my app bootstrapping as a hybrid app, and I've begun converting individual modules and components. I need to be able to do the migration in chunks, though. It would be nice if I could migrate a module at a time, but I'm running into some issues, to that end.
I have a NavBar directive which resides in my core AngularJS module. That component is being downgraded with downgradeComponent and registered on the AngularJS core module. The landing AngularJS module has a dependency on the core module so that it can use the NavBar. This works fine, because the LandingComponent has also been converted to Angular6 and is being downgraded and registered on the landing AngularJS module.
There is a problem with using the NavBar component inside of any other AngularJS component, though. I have a third AngularJS module called workflows with a ViewWorkflows component that has a NavBar inside its template. When I navigate to that component, I get the following error:
angular.js:14791 Error: No component factory found for NavBarDirective. Did you add it to #NgModule.entryComponents?
I can fix this by converting and then downgrading ViewWorkflows, but since NavBar is being registered as a downgraded AngularJS component, shouldn't any AngularJS module that declares a dependency on the core module have access to it?
Code (Not runnable)
Edit: I've updated the gist to be a little more simple. The landing module is Angular, with an Angular component, <landing> that is downgraded to run on the AngularJS landing module and has a <t-nav-bar> inside it. It has a dependency on the core module which provides the downgraded <t-nav-bar> directive. The <test> component is an AngularJS component registered on the AngularJS landing module that cannot use the <t-nav-bar>. Without even bringing the workflows module into the situation, it doesn't work. What am I doing wrong?
I have managed to sort this out. I was trying to declare the NavBar as an Angular #Directive. It actually needs to be a #Component. After making that switch, it works exactly as expected.
I spun up this repo to test with, and discovered the issue there. It's a new Angular 6 app that I "downgraded" for experimenting.

How to use a directive as an entry point when using angular's bootstrap function?

I have an angular 1 app that's being bootstrapped onto a Java web page (legacy app) using ng-app tags. I'm trying to create a hybrid app using Angular 2's downgrade capabilities.
In order to do this I need to remove ng-app tags and use the UpgradeModule from #angular/upgrade/static and bootstrap using the upgrade.bootstrap(document.body, ['myapp']). However, most of the components of the app, including the entry point of the app, are just plain old angular 1.2 directives.
From the examples I've seen, they are using the controller="MenuCtrl" syntax to add components to the page. Is it possible to use directives as the entry point to the app? e.g.
<div my-menu-directive></div>
Currently, nothing is showing up in the app since I've removed the ng-app tags, but the app is definitely being bootstrapped. I'm just not seeing any of the directives.
Fixed this by wrapping the bootstrap statement in angular.element() like so:
angular.element(function() {
upgrade.bootstrap(document.body, ['myApp'], { strictDi: true });
});

What needs to be done to call third party Reactjs component from Anguarjs 1 using ngReact?

I have an existing Angularjs application, and I would like to start using Reactjs.
I tried ngReact, I can create my own Reactjs component using React.createClass and reactDirective, and Angular is able call this directive successfully. I am only using bower to add dependencies for angular, react, and ngReact, I am not using any other tools like gulp, grunt, webpack, etc.
The main reason that I would like to use Reactjs is to invoke third party Reactjs components, which is created using Reactjs, not created using ngReact. I could not find an example that is doing this. What do I need to do to make the Angular application to find the Reactjs components and invoke it?
My angularjs 1.4 app was also not using common UI build tools like webpack. I wanted to introduce some react components, and this was my approach.
I created a file, angularModuleOfReactComponents.js.
It imports react components, then makes an angular module (reactComponentsModule) to hold them:
import MyComponent from './MyComponent.js';
import AnotherComponent from './AnotherComponent.js';
(function(){
var m = angular.module('reactComponentsModule', []);
m.value('reactMyComponent', MyComponent);
m.value('reactAnotherComponent', AnotherComponent);
})();
You should be able to do something similar by importing third party libraries. You could also write a react class that uses a third party library and import your wrapper class.
I then used Babel to convert my jsx react components and my angularModuleOfReactComponents.js to CommonJS, and then I used browserify to convert to something the browser understands. (Although I used build tools, they do not involve my angular app. And, this isn't my permanent mechanism. This is a two step process that doesn't allow auto recompiling when source is changed. I was just trying to get something to work for proof of concept, and I'll be improving this process soon.)
In my angular app, I load angular library files, then react libraries, then ng-react, then my browserified angularModuleOfReactComponents.js and then my app's angular code (controllers, directives, services, etc.).
To use a react component, I declare a dependency on 'react' (from ng-react) and 'reactComponentsModule':
var myModule = angular.module('myModule', ['react', 'reactComponentsModule']);
And then I can inject whichever component(s) I need:
myModule.controller('myController', ['$scope', '$log', 'reactMyComponent', function($scope, $log, reactMyComponent) {
$scope.myprops = {name:'Jack'};
}]);
In html, ng-react's react-component directive is used like:
<react-component name="reactMyComponent" props="myprops" watch-depth="reference" />
To add on #user3141592 answer, I've done a blog post recently on how you can migrate your angular app to React using webpack and ngReact:
https://www.devpanda.me/2018/02/16/Simple-Angular-and-React-Hybrid-App/
I've posted a github repo as well :
https://github.com/danielcondemarin/angular-react-hybrid

Attribute Directive written in angular2 cannot be used from angular 1 app with downgrade?

This is strange, I was downgrading a lot of components from Angular 2 to Angular 1 app and everything working great. I was thinking directive will work too, but seems they don't?
This is my downgrade of directive:
angular.module('myApp')
.directive('tooltip', downgradeComponent({component: TooltipDirective, inputs: ['tooltip', 'placement']}) as angular.IDirectiveFactory);
Thats not helping. I know that directive is a component without a template, but it still a component.

has ngComponentRouter been released as part of 1.5.5 or is it still in beta?

In bower the angular-component-router package is only at 0.2.1. Is that the right router for angular 1.5.5? Seems weird that the documentation would point to this for Angular 1 if it's not RTM yet.
Thanks in advance.
The current implementation of component router for Angular 1 is depreciated. They are considering to backport Angular 2 component router.
https://docs.angularjs.org/guide/component-router
Deprecation Notice: In an effort to keep synchronized with router
changes in Angular 2, this implementation of the Component Router
(ngComponentRouter module) has been deprecated and will not receive
further updates. We are investigating backporting the Angular 2 Router
to Angular 1, but alternatively, use the ngRoute module or community
developed projects (e.g. ui-router).

Resources