pbastowski / angular2-now

Angular 2 @Component syntax for Angular 1 apps
MIT License
145 stars 15 forks source link

using angular2-now in a meteor package results in "_angular2now is undefined" error #26

Closed thomaskoren closed 8 years ago

thomaskoren commented 8 years ago

given a project setup with the following structure

common-base-package -> client-package -> meteor-app

common-base-package introduces angular2-now (and others) in packages.js:

...
api.imply('pbastowski:angular2-now');
api.imply('pbastowski:ecmascript-extras');
api.imply('pbastowski:require');
...

when importing from angular2-now in client-package: e.g.

import {SetModule} from "angular2now";

and trying to start the app, the following error is shown:

TypeError: _angular2now is undefined

everything works just fine when angular2-now is used from inside a meteor app context.

pbastowski commented 8 years ago

I need more info to help diagnose this issue:

Also, could you share the repo, so I can have a look at it myself?

In any case, the imply methods need a version, otherwise you'll probably get the oldest versions available, which may not have what you need.

api.imply('pbastowski:angular2-now@0.3.14');
api.imply('pbastowski:require@0.0.3');

if you're using the latest version of angular@1.2.2 then I believe it already implies pbastowski:angular-babel. If so, then you'll have to remove packages ecmascript and not imply pbastowski:ecmascript-extras. This is because ecmascript and pbastowski:angular-babel both want to add a build plugin for .js files, which is not allowed by Meteor version 1.2.x.

thomaskoren commented 8 years ago

short reply: according to your input, everything is as it should be.

in detail:

i stripped out everything from my project leaving only code defining dependencies and app startup. see https://github.com/thomaskoren/meteor-angular2now-test

pbastowski commented 8 years ago

I just had a look at your repo, but I can't see how it can work at all when the packages folder is outside of the meteor app itself. What I mean is that the app folders should be structured as shown below. Meteor needs to see your packages folder in the root of your Meteor app.

meteor-angular2now-test/ 
    .meteor   // created by meteor when you did "meteor create meteor-angular2now-test"
    client
        app
            app.js
        feature1
        feature2
    packages
        counter-base
        counter-client
        counter-server
    server
        server-folder-1
        server-folder-2

And then of course you need to add all your custom packages to the Meteor app

meteor add tokilicious:counter-base
meteor add tokilicious:counter-client
meteor add tokilicious:counter-server
pbastowski commented 8 years ago

For instance, I have the setup shown in the picture below, which works just fine. image

Notice that meteor list shows there are only two packages in the meteor project.

thomaskoren commented 8 years ago

the packages get resolved, because of an evironment variable PACKAGE_DIRS which points to a directory containing all my custom packages.

what i ultimately try to achieve here is, to implement one common backend component, which will be accessed by several individual client apps. to prevent data regression errors (and other ugly side effects of separated code bases), i want to share common code via packages between apps. for example:

meteor/
  packages/              //referenced by PACKAGE_DIRS
    base/
    client/              // uses package 'base'
    server/              // uses package 'base'
    ...
  apps/
    backend/             // uses package 'server'
      .meteor/
    client1-web-browser  // uses package 'client', accesses backend via DDP
      .meteor/
    client2-android      // uses package 'client', accesses backend via DDP
      .meteor/

the "leaf projects" ideally contain nothing but the .meteor folder (and maybe some stylesheets and config params).

this setup works great as long as packages only contain "plain" JS. especially for client development it would be great to share angular(2(now)) components via packages. which brings us back to the initial problem: _angular2now only gets resolved if all angular2now code is contained in a single meteor app folder.

if you have any other approaches to achieve such a "multi client" setup, this would be just as great ;)

oh... and thank you for all your help!!

pbastowski commented 8 years ago

You could try using symlinks instead of PACKAGE_DIRS, to make the package's directories appear under the packages directory in your app root.

thomaskoren commented 8 years ago

good point, but stuck on windows here ;)

windows symlinks/junction points are not reliable: write errors, system hangs (especially when the linked dir is being watched by something like a live-compiler). git-submodules are possible, but quite inconvenient (syncing submodule commits with app-repo commits). PACKAGE_DIRS seemed like a nice way to maintain something like a "machine-local package repo".

pbastowski commented 8 years ago

PACKAGE_DIRS seems to work fine for me, see shell log below. But, I'm on OS X, not Windows.

So, I have two directories:

~/tmp/packages
~/tmp/ng2now-bundle

The packages directory is where I put the two package folders base and bundle. The ng2now-bundle folder has only the client directory with three files in it. The rest you can see in the log below.

[~/tmp/ng2now-bundle]
$ export PACKAGE_DIRS="$HOME/tmp/packages"

[~/tmp/ng2now-bundle]
$ ls
client/

[~/tmp/packages]
$ ls
base/   bundle/

[~/tmp/ng2now-bundle]
$ meteor list
angular-base   0.0.1+                         
ng2now-bundle  0.0.1+

+ These packages are built locally from source.

[~/tmp/ng2now-bundle]
$ meteor
[[[[[ tmp/ng2now-bundle ]]]]]  

=> Started proxy.                             
=> Started MongoDB.                           
   Building for web.browser                  
Babel compiling files:
  /packages/pbastowski_angular2-now.js
  client/app.js
=> Started your app.                          

=> App running at: http://localhost:3000/
thomaskoren commented 8 years ago

do you have a js file with something like

import {Component, View, Inject} from "angular2now";

in ~/tmp/packages/bundle/? that's what triggers the error in my setup.

as long as import ... from "angular2now"only exist in the app project folder (in your case ~/tmp/ng2now-bundle) everything works as expected.

pbastowski commented 8 years ago

I've just pushed angular2-now@0.3.15. It should work for you now.

Please let me know if it helped.

pbastowski commented 8 years ago

Under the assumption that it's now working for you, I'm closing this issue. If it doesn't work then let me know.

thomaskoren commented 8 years ago

Sorry, i haven't had time to test your update until now. Your changes look promising, but there might be one final little piece missing: I updated your package and added some simple components to the client sub package. Those components import and use several angular2now elements including: SetModule, Component, View, Inject and State. No more errors during compilation and loading of js files in the browser. But when finally bootsrap(App) is being called, the following error is thrown:

Error: [$injector:modulerr] Failed to instantiate module counter due to:
[$injector:modulerr] Failed to instantiate module angular-meteor due to:
[$injector:unpr] Unknown provider: $urlRouterProvider
http://errors.angularjs.org/1.4.7/$injector/unpr?p0=%24urlRouterProvider
minErr/<@http://localhost:3000/packages/angular_angular.js?0a328c602667881bb749eae26bbfccca25285a42:91:12
createInjector/providerCache.$injector<@http://localhost:3000/packages/angular_angular.js?0a328c602667881bb749eae26bbfccca25285a42:4312:19
getService@http://localhost:3000/packages/angular_angular.js?0a328c602667881bb749eae26bbfccca25285a42:4460:39
invoke@http://localhost:3000/packages/angular_angular.js?0a328c602667881bb749eae26bbfccca25285a42:4492:1
runInvokeQueue@http://localhost:3000/packages/angular_angular.js?0a328c602667881bb749eae26bbfccca25285a42:4407:11
loadModules/<@http://localhost:3000/packages/angular_angular.js?0a328c602667881bb749eae26bbfccca25285a42:4416:11
...

So there might be something missing regarding the @Stateannotation I guess?

pbastowski commented 8 years ago

Hi Thomas. Sorry, I've been busy and only just got back to your question.

I think you might just be missing 'ui.router' in your SetModule dependencies list.

    SetModule('app', ['angular-meteor', 'ui.router']);

And you also have to add ui-router to the package that will be using it

    api.imply('angularui:angular-ui-router');

The above setup works for me.