Question

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.

No correct solution

OTHER TIPS

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

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

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

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

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top