Skip to content

Instantly share code, notes, and snippets.

@Hotell
Last active Aug 29, 2015
Embed
What would you like to do?
Mapping Angular 1 to ReactJS Api

Angular Component composition via ReactJS style API

This is my recomendation how to write angular components with leveraging react style component API naming.

And Remember, Respekt is everything! :)

Notes

  • ny - is not new york :D, it's our meetup group prefix ngParty, come to our meetup yo ngParty

@TODO

  • Tweak examples via ES7/TS decorators
  • some other todo

// UI State model
class NyComponentState{

  // if the tooltip should be shown
  // component decorators can modify this property.
  shouldShow: boolean;
  
  // if the tooltip is currently being shown. 
  // Component decorators can use this property to test if the tooltip is being shown
  isShowing: boolean;
  
  // the message the tooltip contains. It is an angular expression
  message: string;
  
  // the x coordinate of the tooltip
  x: number;

  // the y coordinate of the tooltip
  y: number;
  
  constructor({shouldShow=true,isShowing=false,message='',x=0,y=0}=<NyComponentState>{}){
  
    Object.assign(this,{shouldShow,isShowing,message,x,y})
    
  }

}


interface IComponent<T> extends IDirective<T>{}
interface IDirective<T>{
  state: T
  setState(T): void,
  componentDidMount(...args): void
  componentWillUnmount(...args): void;
}

// Component definition
class NyComponent implements IComponent<NyComponentState>{

  // #state
  private state: NyComponentState;
  
  private ngModel: ng.INgModelController;
  
  // #getInitialState
  constructor(private ComponentState: NyComponentState){
    this.setState(ComponentState())
  }
  
  // #setState
  private setState(statePropertiesToSet){
    Object.assign(this.state, statePropertiesToSet)
  }
  
  // #componentDidMount
  componentDidMount(ngModel){
  
    // assign provided controllers
    this.ngModel = ngModel;
    
  }
  
  // #componentWillUnmount
  componentWillUnmount(){
   // paste here logic that you want handle on $scope#$destroy
  }
  
  // some custom controller method for changing position
  setPosition(x: number, y: number) {
  
    this.setState({x,y})
    
  }
  
}
function nyComponent(){
  return {
    controller: NyComponent,
    controllerAs:'ctrl',
    scope: {},
    bindToController:{},
    require:['nyComponent','ngModel'],
    link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, controller: [NyComponent, ng.INgModelController])=>{
      
      // set controllers
      const [ctrl, ngModel] = controller;
      
      // handle mount
      // we can pass aditional controllers if any are required and process the logic inside controller
      ctrl.componentDidMount(ngModel);
      
      // handle destroy
      scope.$on('$destroy',ctrl.componentWillUnmount);
      
      // handle host events
      //
      // @Todo move this to decorator
      // - this will be handled via 
      //  @Component({
      //    host:{
      //      '(focus)': 'onFocus()',
      //      '(mouseenter)': 'logCoordinates()'
      //    }
      //  })
      const hostListeners = {
        'focus': ctrl.onFocus,
        'mouseenter': ctrl.logCoordinates
      };
      angular.forEeach(hostListeners,(listener, eventName)=>{ element.on(eventName, listener.bind(ctrl)); }); 
      element.on('$destroy',(e)=>element.off(...Object.keys(hostListeners));
      
    }
  };
}


// register to angular
const ngModule = angular.module('nyReactStyleApp',[]);

ngModule
  .directive(nyComponent.name, nyComponent)
  .value('NyComponentState', NyComponentState);
  
angular.bootstrap(document,[ngModule.name]);
 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment