26

I am trying to use ReactJS with AngularJS but it is not working out. Could anyone please direct me on how to gel them together? Or please point out what am missing here?

My index.html is as follows:

<!DOCTYPE html>
<html data-ng-app="MyApp">
    <head>
        <title>My Test</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body data-ng-controller="Ctrl1">
        <div id="myDiv">
            <button id="btn1" data-ng-click="clickMe()">Click Me</button>
        </div>
        <script src="http://fb.me/react-0.8.0.js"></script>
        <script src="http://fb.me/JSXTransformer-0.8.0.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js"></script>
        <script type="text/jsx" src="reactExample.js"></script>
        <script src="angularExample.js"></script>
    </body>
</html>

Here is how my reactExample.js has been written:

/**
  * @jsx React.DOM
  */
var testMy = React.createClass({
    render: function(){
        return ( <p>Hello</p>)
    }
});

And my angularExample.js is as follows:

var myapp = angular.module('MyApp',[]);
myapp.controller('Ctrl1',['$scope',function($scope){
    $scope.clickMe = function(){
        alert("Clicked!");
        React.renderComponent(testMy, elem[0]);
    }
}]);

It does not display anything (other than the alert). Am expecting to see 'Hello' printed there but it throws the following error in the console:

Error: Invariant Violation: prepareEnvironmentForDOM(...): Target container is not a DOM element

Any help would be much appreciated.

1
  • Maybe fix your code samples? The formatting is hard to read Commented Jan 6, 2014 at 16:54

5 Answers 5

20

Already @Simon Smith mentioned why the error occour React.renderComponent expect second argument but the way you play DOM manipulation inside controller is not appropriate. In AngularJs DOM manipulation should be in directive. Lets see how it could be

From Facebook's React vs AngularJS: A Closer Look blog

React components are far more powerful than Angular templates; they should be compared with Angular's directives instead.

Bottom of this blog Using React and AngularJS together section you can see how angular and react can play together.

From react website

React components implement a render() method that takes input data and returns what to display.

In angularjs components are rendered by directive

See this plunker where I integrate angularjs and react.

In react-example.js I have created virtual dom element

var Hello = React.createClass({
  render: function() {
    return React.DOM.div({}, 'Hello ' + this.props.name);
  }
});

And myMessage directive render the virtual dom

React.renderComponent(Hello({name: scope.myModel.message}), document.getElementById('example'));

Where virtual dom's name property will bind with scope.myModel.message

Sign up to request clarification or add additional context in comments.

2 Comments

I have forked the plunker and modified it so that the Hello component is contained within the directive: plnkr.co/edit/3ImY8G7X1VfvOeKrC8DY?p=preview @Reza does this make much sense?
Technically this is not a problem but Separation of Concern (SoC) and test-ability perspective it is better to place your react classes into different files.
12

To use React in my controller, i do this

 myApp.controller(function($scope){
        $scope.myComponent = {};
        $scope.myComponent.setState({data: "something"});
    });

and in my React component:

window.myComponent = React.createClass({
    getInitialState: function(){
        return {
           data:''
        }
    },
    componentWillMount: function(){
       var scope = this.props.scope;
           scope.myComponent = this;
    },
    render:func .....
});

I'm using the ngReact directive from David Chang, which passes the $scope as a property into a component. So now you can call setState from your controller, forcing the react component to re-render :)

I have a bigger example of above in my React-Sandbox

1 Comment

How would data binding work the other way? Say your react component has an input and you want to update the angular scope when the input changes. Is this possible with the react-component directive from ngReact.
9

I would consider doing the integration via a directive as that is often the recommended approach for integrating non angular code with angular.

Here is an example:

angular.module('app').directive('greeting',[function(){
    return {
        restrict:'AE',
        scope:{name:'@'},
        link: function (scope, elem, attrs){
            var GreetingSection = React.createClass({displayName: 'Greeting',
                render: function() {
                    var message = "Good morning " + this.props.data.name + ", how are you?";
                    return React.createElement('div', {className: "greeting"},message);
                }
            });
            React.renderComponent(GreetingSection({data:scope}), elem[0]);
        }
    };
}]);

More info here (link died; points to archive.org copy):
http://www.syntaxsuccess.com/viewarticle/547bbd04fa0710440b45e41c

3 Comments

Can you explain why I was getting this error when using this code? Cannot read property '__reactAutoBindMap' of undefined at ReactClass.createClass.Constructor I had to instead use React.createFactory to create a greetingFactory variable and pass the greetingFactory variable into React.render instead of React.renderComponent.
@taco In the latest version of react (v0.14.x), you need to do ReactDOM.render(React.createElement(GreetingSection, null), elem[0]); to avoid this error. See link
@DamianGreen maybe that will help somebody else. Thanks
3

Instead try using ngReact angular module rather than using ReactJs directly. This provides seamless integration with angularJs as well. Check the samples/examples @ https://github.com/davidchang/ngReact

Comments

2

renderComponent expects a DOM element as a second argument to inject the component. It seems that is what the error is complaining about.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.