pbastowski / angular2-now

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

I'm not sure if my controllers are being created properly. #13

Closed vacarsu closed 9 years ago

vacarsu commented 9 years ago

I have a state setup as follows

@State({
  name: 'root.register',
  url: '/register',
  templateUrl: 'client/components/register/register.ng.html'
})
@Inject(['$rootScope', '$meteor', '$state'])

class register {
  constructor($rootScope, $meteor, $state) {
    this.$meteor = $meteor;
    this.$state = $state;
    console.log($rootScope.currentUser);
  }

  register(user) {
    this.$meteor.createUser({
      username: user.email,
      email: user.email,
      profile: {
        displayName: user.firstName + ' ' + user.middleInitial + ' ' + user.lastName,
        firstName: user.firstName,
        middleInitial: user.middleInitial,
        lastName: user.lastName,
        accountType: user.accountType
      },
      password: user.password
    })
    .then(() => {
      this.$state.go('root.home');
    },
    err => {
      console.log(err);
    })
  }
}

I have tried accessing the register function in the template via register.register(), and I have also tried setting the scope name via angular2now.options({ controllerAs: 'vm' }); in app.es6.js. Both ways seem to not work. However, when I go to the state at /register the $rootScope.currentUser does get logged as undefined which is expected.

pbastowski commented 9 years ago

The reason why register.anything is not working is because you don't have a @Component defined for this route. Only components create their own private scope that you can access through the camelCased component selector name, in your case register.

The example code is what I would call the "old" way of defining routes with controllers and templates :)

Consider doing it this way instead:

@State({
  name: 'root.register',
  url: '/register',
})

@Component('register')  // shortcut for selector: 'register'
@View('client/components/register/register.ng.html')  // shortcut for templateUrl: '....'
@Inject(['$rootScope', '$meteor', '$state'])

class register {
  constructor($rootScope, $meteor, $state) {
    this.$meteor = $meteor;
    this.$state = $state;
    console.log($rootScope.currentUser);
  }

  register(user) {
    this.$meteor.createUser({
      username: user.email,
      email: user.email,
      profile: {
        displayName: user.firstName + ' ' + user.middleInitial + ' ' + user.lastName,
        firstName: user.firstName,
        middleInitial: user.middleInitial,
        lastName: user.lastName,
        accountType: user.accountType
      },
      password: user.password
    })
    .then(() => {
      this.$state.go('root.home');
    },
    err => {
      console.log(err);
    })
  }
}

With the above change, you will have access in your template to register.register(user).

Alternatively, you could inject $scope into the constructor and put all your functions on $scope. But, with angular2now we are trying to move away from controllers and scope on to components.

...
@Inject([ '$rootScope', '$meteor', '$state', '$scope' ])

class register {
  constructor($rootScope, $meteor, $state, $scope) {
    $scope.register = function () { .... }
...

The above is not what I designed angular2now for.
vacarsu commented 9 years ago

Okay that makes sense, so I must create a component for it, but I don't necessarily have to use the selector for it?

pbastowski commented 9 years ago

Each component always has a selector.

Have a look at this example to see how it all fits together. It is in ES5, but you will notice familiar things:

http://plnkr.co/edit/uxV781?p=preview

vacarsu commented 9 years ago

Thanks for that example, I get it now. Got it all working.