Git Product home page Git Product logo

ngreact's Introduction

Build Status Pair on this

Note: For a more modern alternative to ngReact, we recommend react2angular, angular2react, and ngimport.

ngReact

The React.js library can be used as a view component in web applications. ngReact is an Angular module that allows React Components to be used in AngularJS applications.

Motivation for this could be any of the following:

  • You need greater performance than Angular can offer (two way data binding, Object.observe, too many scope watchers on the page) and React is typically more performant due to the Virtual DOM and other optimizations it can make

  • React offers an easier way to think about the state of your UI; instead of data flowing both ways between controller and view as in two way data binding, React typically eschews this for a more unidirectional/reactive paradigm

  • Someone in the React community released a component that you would like to try out

  • You're already deep into an Angular application and can't move away, but would like to experiment with React

Installation

Install via Bower:

bower install ngReact

or via npm:

npm install ngreact

Usage

Then, just make sure Angular, React, and ngReact are on the page,

<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/react/react.js"></script>
<script src="bower_components/react/react-dom.js"></script>
<script src="bower_components/ngReact/ngReact.min.js"></script>

and include the 'react' Angular module as a dependency for your new app

<script>
    angular.module('app', ['react']);
</script>

and you're good to go.

Features

Specifically, ngReact is composed of:

  • react-component, an Angular directive that delegates off to a React Component
  • reactDirective, a service for converting React components into the react-component Angular directive

ngReact can be used in existing angular applications, to replace entire or partial views with react components.

The react-component directive

The react-component directive is a generic wrapper for embedding your React components.

With an Angular app and controller declaration like this:

angular
  .module('app', ['react'])
  .controller('helloController', function($scope) {
    $scope.person = { fname: 'Clark', lname: 'Kent' };
  });

And a React Component like this

var HelloComponent = React.createClass({
  propTypes: {
    fname: React.PropTypes.string.isRequired,
    lname: React.PropTypes.string.isRequired
  },
  render: function() {
    return (
      <span>
        Hello {this.props.fname} {this.props.lname}
      </span>
    );
  }
});
app.value('HelloComponent', HelloComponent);

The component can be used in an Angular view using the react-component directive like so:

<body ng-app="app">
  <div ng-controller="helloController">
    <react-component name="HelloComponent" props="person" watch-depth="reference"/>
  </div>
</body>

Here:

  • name attribute checks for an Angular injectable of that name and falls back to a globally exposed variable of the same name
  • props attribute indicates what scope properties should be exposed to the React component
  • watch-depth attribute indicates what watch strategy to use to detect changes on scope properties. The possible values for react-component are reference, collection and value (default)

The reactDirective service

The reactDirective factory, in contrast to the reactComponent directive, is meant to create specific directives corresponding to React components. In the background, this actually creates and sets up directives specifically bound to the specified React component.

If, for example, you wanted to use the same React component in multiple places, you'd have to specify <react-component name="yourComponent" props="props"></react-component> repeatedly, but if you used reactDirective factory, you could create a <your-component></your-component> directive and simply use that everywhere.

The service takes the React component as the argument.

app.directive('helloComponent', function(reactDirective) {
  return reactDirective(HelloComponent);
});

Alternatively you can provide the name of the component

app.directive('helloComponent', function(reactDirective) {
  return reactDirective('HelloComponent');
});

This creates a directive that can be used like this:

<body ng-app="app">
  <div ng-controller="helloController">
    <hello-component fname="person.fname" lname="person.lname" watch-depth="reference"></hello-component>
  </div>
</body>

The reactDirective service will read the React component propTypes and watch attributes with these names. If your react component doesn't have propTypes defined you can pass in an array of attribute names to watch. If you don't pass any array of attribute names, fall back to use directive attributes as a last resort. By default, attributes will be watched by value however you can also choose to watch by reference or collection by supplying the watch-depth attribute. Possible values are reference, collection and value (default).

app.directive('hello', function(reactDirective) {
  return reactDirective(HelloComponent, ['fname', 'lname']);
});

You may also customize the watch depth per prop/attribute by wrapping the name and an options object in an array inside the props array:

app.directive('hello', function(reactDirective) {
  return reactDirective(HelloComponent, [
    'person', // takes on the watch-depth of the entire directive
    ['place', { watchDepth: 'reference' }],
    ['things', { watchDepth: 'collection' }],
    ['ideas', { watchDepth: 'value' }]
  ]);
});

By default, ngReact will wrap any functions you pass as in scope.$apply. You may want to override this behavior, for instance, if you are passing a React component as a prop. You can achieve this by explicitly adding a wrapApply: false in the prop config:

app.directive('hello', function(reactDirective) {
  return reactDirective(HelloComponent, [
    'person',
    ['place', { watchDepth: 'reference' }],
    ['func', { watchDepth: 'reference', wrapApply: false }]
  ]);
});

If you want to change the configuration of the directive created the reactDirective service, e.g. change restrict: 'E' to restrict: 'C', you can do so by passing in an object literal with the desired configuration.

app.directive('hello', function(reactDirective) {
  return reactDirective(HelloComponent, undefined, { restrict: 'C' });
});

Minification

A lot of automatic annotation libraries including ng-annotate skip implicit annotations of directives. Because of that you might get the following error when using directive in minified code:

Unknown provider: eProvider <- e <- helloDirective

To fix it add explicit annotation of dependency

var helloDirective = function(reactDirective) {
  return reactDirective('HelloComponent');
};
helloDirective.$inject = ['reactDirective'];
app.directive('hello', helloDirective);

Reusing Angular Injectables

In an existing Angular application, you'll often have existing services or filters that you wish to access from your React component. These can be retrieved using Angular's dependency injection. The React component will still be render-able as aforementioned, using the react-component directive.

It's also possible to pass Angular injectables and other variables as fourth parameter straight to the reactDirective, which will then attach them to the props

app.directive('helloComponent', function(reactDirective, $ngRedux) {
  return reactDirective(HelloComponent, undefined, {}, { store: $ngRedux });
});

Be aware that you can not inject Angular directives into JSX.

app.filter('hero', function() {
  return function(person) {
    if (person.fname === 'Clark' && person.lname === 'Kent') {
      return 'Superman';
    }
    return person.fname + ' ' + person.lname;
  };
});

/** @jsx React.DOM */
app.factory('HelloComponent', function($filter) {
  return React.createClass({
    propTypes: {
      person: React.PropTypes.object.isRequired
    },
    render: function() {
      return <span>Hello $filter('hero')(this.props.person)</span>;
    }
  });
});
<body ng-app="app">
  <div ng-controller="helloController">
    <react-component name="HelloComponent" props="person" />
  </div>
</body>

Jsx Transformation in the browser

During testing you may want to run the JSXTransformer in the browser. For this to work with angular you need to make sure that the jsx code has been transformed before the angular application is bootstrapped. To do so you can manually bootstrap the angular application. For a working example see the jsx-transformer example.

NOTE: The workaround for this is hacky as the angular bootstap is postponed in with a setTimeout, so consider transforming jsx in a build step.

Usage with webpack and AngularJS < 1.3.14

CommonJS support was added to AngularJS in version 1.3.14. If you use webpack and need to support AngularJS < 1.3.14, you should use webpack's exports-loader so that require('angular') returns the correct value. Your webpack configuration should include the following loader config:

...
module: {
  loaders: [
    {
      test: path.resolve(__dirname, 'node_modules/angular/angular.js'),
      loader: 'exports?window.angular'
    }
  ]
},
...

Developing

Before starting development run

npm install
bower install

Build minified version and run tests with

grunt

Continually run test during development with

grunt karma:background watch

Running the examples

The examples in the examples/ folder use bower_components. To install these first install bower on your machine

npm install --global bower

Then install the bower components

bower install

The examples need to be run on a local webserver like https://www.npmjs.com/package/http-server.

Run the examples by starting a webserver in the project root folder.

Community

Maintainers

  • Kasper Bøgebjerg Pedersen (@kasperp)
  • David Chang (@davidchang)

Contributors

  • Matthieu Prat (matthieuprat)
  • @Shuki-L
  • Fabien Rassinier (@frassinier)
  • Guilherme Hermeto (@ghermeto)
  • @thorsten
  • @katgeorgeek
  • @rosston
  • Tihomir Kit (@pootzko)
  • Alexander Beletsky (@alexanderbeletsky)
  • @matthieu-ravey
  • @ethul
  • Devin Jett (@djett41)
  • Marek Kalnik (@marekkalnik)
  • @oriweingart
  • Basarat Ali Syed (@basarat)
  • Rene Bischoff (@Fjandin)
  • Zach Pratt (@zpratt)
  • Alex Abenoja (@aabenoja)
  • @villesau
  • @bdwain
  • @onumossn

ngreact's People

Contributors

aabenoja avatar akprasad avatar albatrosary avatar alexbeletsky avatar basarat avatar bcherny avatar bdwain avatar cmrnh avatar codef0rmerz avatar davidchang avatar djett avatar ethul avatar fjandin avatar ghermeto avatar hasdavidc avatar hillmanov avatar kasperp avatar marekkalnik avatar matthieuprat avatar maxim-filimonov avatar onumossn avatar oriweingart avatar pennycoders avatar pgs-pliulia avatar posva avatar rosston avatar thorsten avatar tiffanywang3 avatar tihomir-kit avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ngreact's Issues

Include React Templates as ngReact directives?

Hey, I'm testing this project and just found React Templates and seems there's some useful ones like rt-repeat and similarly useful stuff. I was wondering if that could be included as a part of ngReact to use as drop-in replacements for AngularJS directives, like using rt-repeat instead of ng-repeat and automatically having the benefits of React rendering.
I would contribute to that but i'm still a bit alien to this project. Let me know if you guys can help me getting started with ngReact internals so that i can contribute or you also think it's a good idea and can work on that.
Best!

Update npm package to latest

Current npm package still includes the CommonJs bug (where root is passed to the factory function as an extra param in the CommonJs check). The people who run into the bug are also the people who don't have the fix 😄

Directive configuration

Could it be possible to extend the created directive with custom configuration? For instance i need the directive to be restricted to class.
Could be something like:

var reactDirective = function($timeout, $injector) {
    return function(reactComponentName, propNames, directiveConfig) {
        var defaultDirectiveConfig = {
            restrict: 'E',
            replace: true,
            link: function(scope, elem, attrs) {
                var reactComponent = getReactComponent(reactComponentName, $injector);

                propNames = propNames || Object.keys(reactComponent.propTypes || {});

                var renderMyComponent = function() {
                    var props = {};
                    propNames.forEach(function(propName) {
                        props[propName] = scope.$eval(attrs[propName]);
                    });
                    renderComponent(reactComponent, applyFunctions(props, scope), $timeout, elem);
                };

                // watch each property name and trigger an update whenever something changes,
                // to update scope.props with new values
                propNames.forEach(function(k) {
                    scope.$watch(attrs[k], renderMyComponent, true);
                });

                renderMyComponent();

                // cleanup when scope is destroyed
                scope.$on('$destroy', function() {
                    React.unmountComponentAtNode(elem[0]);
                });
            }
        };

        return angular.extend(defaultDirectiveConfig, directiveConfig)
    };
};

React directive doesn't seem to play nice with minification

Hi,
I have noticed that when we use reactDirective service to return directive to render react component it all works perfectly in development. But our production or staging environment it breaks due to minification with the following error:

Error: Unknown provider: eProvider <- e <- profileDirective
    at Error (native)
    at http://docker.dev:32782/assets/application-e221692873df2eda5137ebaf04fd1dcb.js:19:6399
    at Object.n [as get] (http://docker.dev:32782/assets/application-e221692873df2eda5137ebaf04fd1dcb.js:19:5379)
    at http://docker.dev:32782/assets/application-e221692873df2eda5137ebaf04fd1dcb.js:19:6461
    at n (http://docker.dev:32782/assets/application-e221692873df2eda5137ebaf04fd1dcb.js:19:5379)
    at Object.i [as invoke] (http://docker.dev:32782/assets/application-e221692873df2eda5137ebaf04fd1dcb.js:19:5513)
    at http://docker.dev:32782/assets/application-e221692873df2eda5137ebaf04fd1dcb.js:19:10193
    at Array.forEach (native)
    at r (http://docker.dev:32782/assets/application-e221692873df2eda5137ebaf04fd1dcb.js:18:26285)
    at Object.<anonymous> (http://docker.dev:32782/assets/application-e221692873df2eda5137ebaf04fd1dcb.js:19:10162)

Any ideas ? It looks like angular is starting to parse html and look for directives before reactDirective returns but i'm not sure why does it only happens after minification.
Also when pocking injector in browser window i can see the following:

angular.element($0).injector().get('profileDirective')
-> []

Can this be used with ngTasty?

I like the features of the tables in ngTasty, but rendering is still pretty slow. I'd like to know if anyone has used ngReact with the ngTasty tables...

publish new version to npm

Looks like there've been some features added to master that aren't in the npm module. Would you mind publishing the latest? Pretty please :)

small issue in documentation for directive factory example

Hi, just checking out your library and toying with the examples.

In your reactDirective example code:

app.directive('hello', function(reactDirective) {
  return reactDirective('Hello');
} );

This causes errors for me: Unknown provider: HelloProvider <- Hello

I figured out the problem. For the docs to be consistent, it should be changed to:

app.directive('hello', function(reactDirective) {
  return reactDirective('HelloComponent');
} );

Am I missing anything?

For what it's worth, I'm working in coffeescript, so my component looks like this:

# HelloComponent.js.coffee
# @cjsx React.DOM
Hello = React.createClass
  propTypes:
    fname : React.PropTypes.string.isRequired
    lname : React.PropTypes.string.isRequired
  render: () ->
    return <span>Hello {this.props.fname} {this.props.lname}</span>
@app.value('HelloComponent', Hello)
@app.directive('hello', (reactDirective) -> return reactDirective('HelloComponent'))

Error: Cannot find module 'ngreact' - during browserify of app

As ngreact just installed I cannot use it in browserify application due to such error,

$ grunt dev
Running "browserify:dev" (browserify) task
>> Error: Cannot find module 'ngreact' from '/Users/alexanderbeletsky/Development/Projects/mylorry/visualization/public/js'
Warning: Error running grunt-browserify. Use --force to continue.

Question about getting it integrated to an Angular app

This lib looks very promising, but I'm struggling to get it working.

I tried pulling in the HelloComponent example into my app, but I get the following error: Unknown provider: HelloComponentProvider <- HelloComponent

In the readme examples, JSX code and JS code is mixed. I assumed this was just for brevity and then proceeded to define my HelloComponent in a separate JSX file and adding it to my apps html page with a type="text/jsx" attribute.

So I'm unsure of the correct way to add the JSX code to my app, it seems like it's only compiled and executed after my app tries to render the HelloComponent control using the reactComponent directive.

Should I rather precompile the JSX or something?

Use react.min.js

The unminified version has a lot of assertions that are useful for development but are slowing down the build. If you use the minified version they all go away and you should get a performance speedup.

Scope functions

How to call a scope function from react component?

Could you put a simple example of how to call a function in angular controller from onClick event of a react component?

Thanks in advance!

Question: How do I pass Angulasr services to my ngReact directive

Hello,

I'm developing under a AngularJS app, and been forced to included a directive using React. I'm struggling looking for documentation on how to pass data to my React component. Basically I need access to my Service/Factory existent methods in my React Component

My code is the following:

/* global React */

var AngularAPP = angular.module('ffa.ui.facilityBookingNg');

var TodoList = React.createClass({
  render: function() {
    var createItem = function(itemText, index) {
      return <li key={index + itemText}>{itemText}</li>;
    };
    return (<ul>{this.props.items.map(createItem)}</ul>);
  }
});

var TodoApp = React.createClass({
  propTypes: {
    name: React.PropTypes.string.isRequired,
    text: React.PropTypes.string.isRequired
  },

  getInitialState: function() {
    return {items: [], text: ''};
  },

  // getDefaultProps: function() {
    // return {
      // items: [],//this.props.items,
      // text: ''
    // };
  // },

  onChange: function(event) {
    this.setState({text: event.target.value});
  },

  handleSubmit: function(event) {
    event.preventDefault();
    var nextItems = this.state.items.concat([this.state.text]);
    var nextText = '';
    this.setState({items: nextItems, text: nextText});
  },

  render: function() {
    return (
      <div>
        <h3>TODO</h3>
        <TodoList items={this.state.items} />
        <form onSubmit={this.handleSubmit}>
          <input onChange={this.onChange} value={this.state.text} />
          <button>{'Add #' + (this.state.items.length + 1)}</button>
        </form>
      </div>
    );
  }
});

AngularAPP.value('TodoApp', TodoApp);
AngularAPP.directive('roomRentalQuickBooking', ['reactDirective', function(reactDirective){
  return reactDirective('TodoApp');
}]) ;

So I would be great if I could do something like this:

AngularAPP.directive('roomRentalQuickBooking', ['reactDirective', 'MainService', function(reactDirective, MainService){
  return reactDirective('TodoApp'); // <- SomeHow Pass/Inject my 'MainService' into 'TodoApp'
}]) ;

Any Suggestions ?

Ty,
AeMonge

Callback losing scope.$apply() wrapper after another prop changes

I'm using the react-component directive with props set to something like

{
  clicked: function() {
    $scope.count += 1;
  },
  name: 'blah'
}

The React component calls this.props.clicked when it is clicked. If I change another prop (e.g. name in the above snippet) on the angular side then it seems as if clicked is no longer called in a scope.$apply() block.

I didn't explain this very well, but here is a plunker demonstrating the issue: http://plnkr.co/edit/pbps2zuUmcrCrrsY2rU1?p=preview

Am I doing something wrong here?

Controller <-> Directive communication

Hi guys I'm trying to modify the value of an angular controller from the angular directive; so lets suppose I have this code:

Application

var fooComponent = React.createClass({
  getInitialState: function() {
    return {
      foo: this.props.foo
    };
  },

  handleChange: function(e) {
    this.setState({foo: e.target.value});
  },

  render: function() {
    return (
      <input type="text" value={this.state.foo} onChange={this.handleChange}/>
    );
  }
});

app = angular.module('app', ['react']).controller('helloController', function($scope) {
    $scope.componentProps = {foo: "bar"};
});

app.value('fooComponent', fooComponent);

Hello Template

<body ng-app="app">
  <div ng-controller="helloController">
    {{componentProps.foo}}
    <react-component name="fooComponent" props="componentProps" watch-depth="reference"/>
  </div>
</body>

What I want it's whenever the fooComponent changes their state, the angular controller notice that change and render their value.

Do you think that this it's possible guys? In case of not, can you tell me why not, and what are the alternatives?

Thanks you much for the lib, looking forward to your answer :)

Possible Performance Boost

I don't know all of the low level stuff in angular, but looking at ngReactRepeat there might be a way to optimize it.

If you can take the nodes that would be transcluded, and instead generate a simple tree of them, along with an array of keys to watch when the directive is compiled, you could use that in the component's render for more efficiency.

If you could get it to the point where e.g. the html is retrieved at compile time, transclusion doesn't happen, and that can be made available to the reactUnit::render as props, I can do the rest.

react-component does not show a list of items in AngularJS

i posted the same question on stackover here: http://stackoverflow.com/questions/29900525/ngreact-react-component-does-not-show-a-list-of-items-in-angularjs , but briefly, my issue is the list of items doesn't show up in the view html:

<react-component name="NewsTableComponent" props="newsItems" watch-depth="reference" />

The NewsTableComponent is set as a value for the the angular module, and it is defined as following:

var NewsTableComponent = React.createClass({
    render: function() {
        return (
                <table className="table table-striped">
                <thead>
                <th>Title</th>
                <th>Source</th>
                <th>Index</th>
                </thead>
                <tbody>
                {
                    this.props.items.map(function(item, index) {
                        return <NewsEntry news={item} key={index} />
                    })
                }

                </tbody>
                </table>
            );
    }
});

var NewsEntry = React.createClass({
    render: function() {

        var curNews = this.props.news;
        var newsRowArr = Object.keys(curNews).map(function(key) {
            return curNews[key];
        });

        return (
            <tr>
            {newsRowArr.map(function(val, index) {
                console.log('val = ', val);
                return <td key={index}>{val}</td>
            })}
            </tr>

            );
    }
});

In the Chrome browser console, I can see the console.log() printings, but the the following list of items are not showing up in the view. I am wondering what's the issue?

$scope.newsItems = {items: [{
    title: "Breaking News",
    source: "CNN",
    index: 1
        },

        {
    title: "Politics",
    source: "Fox News",
    index: 2
        }
    ]};

React is not defined

Hi,

I'm trying to integrate angular with react using your library. I'm building my project with gulp. I've required the angular module, the react module and the ngReact module. I have the ngReact added to my app module but I get an 'React not defined' error when rendering my views.

Any help?

Thanks

Watch expression initial value false-positive

I realize we just merged #57 but after using this a bit more, I've come across a case where I am getting an initial value in the watch expression that is different from the value first passed to the directive wrapping the react component.

For example:

function FooController($q) {
  var that = this;

  this.values = [1,2,3];

  $q.when([4,5,6]).then(function(as) { that.values = as; });
}
<div ng-controller="FooController as foo">
  <foo-react-component values="foo.values" watch-depth="reference"></foo-react-component>
</div>

In this case, the FooReactComponent's render function will be invoked with [1,2,3]. And I would expect it to be then be invoked with [4,5,6] as a result of the watch expression on foo.values. However, the watch expression is initialized with newValue === [4,5,6] and oldValue === [4,5,6], and so from #57, the render function will not be invoked (I am not sure why the oldValue is not [1,2,3]).

One way that I think this can be fixed is that we really want to compare newValue in the watch expression with the initial value passed in the props when the react component is first rendered. And these initial values could be stored when the scope.$eval is called to obtain them. I can write up a PR to illustrate this, but I am wondering if this is getting too complicated. Maybe the multiple render calls is not that big of a deal.

What are your thoughts?

Is this still being developed?

Hi,

I'm really intrigued about using React with AngularJS. This project hasn't seen activity in over a month, is this still being developed? I'd love to see this project go on.

Thanks!

Same semver have different dependencies

The version from npm package.json,

  "version": "0.1.0",
  "dependencies": {
    "angular": "~1.2.20",
    "react": "~0.11.2"
  },

The currently actual version package.json,

  "version": "0.1.0",
  "dependencies": {
    "angular": "1.2.23",
    "react": "0.12.0"
  },

Seems like version should be up to "0.2.0" to have react "0.12.0" and package should be published.

Add example for interacting with react inputs

I have an angularjs application that needs to use a reactjs component. The component contains a few input and select elements. When the inputs change, angularjs should be notified about that somehow (via events, callback functions, or something else). I'd want a function on the $scope called, or the model updated, or something.

I think this is a fairly common use case, but I couldn't find any documented/blessed way of doing so with this library.

Using a directive inside a React component

Hi,

I'm trying to check if it is possible to use directives inside a react component.

The naive approach (just keeping the directive in the JSX) is obviously not working. So I tried to inject the scope and compile the directive by myself, but it seems that injecting the whole scope is not possible. Do you have any idea if it is doable? If not, I think it would be nice to mention it in the documentation, as it may be an important reason to avoid using React.

Option in directive for watch / watchCollection / deep watch comparison

By default the ngReact directives use deep watch comparison which can be pretty expensive and/or unnecessary depending on your data.

What do you think about adding a watchType or something similar that would allow us to define how to watch the incoming react data? Just a thought.

Also, not sure if you need another issue for this, but the replace property for directives has been deprecated, although one could argue that the next major release, 2.0, will be so different that it may not even be a big deal or a deal at all lol!

Trying to get react-canvas working with ngReact

Hi,

ngReact is easy to install and to use with angularjs...
... but how to proceed when you want to use a react library like flipboard/react-canvas as it relies on requirejs.

I tried without success to load react and react-canvas with browserify.
Maybe I'm on the wrong way ?

oliver

React ref not working

For example

render() {
 return <div ref="sample"></div>
}

will cause exception

Error: Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. This usually means that you're trying to add a ref to a component that doesn't have an owner (that is, was not created inside of another component's render method). Try rendering this component inside of a new top-level component which will hold the ref.

Function property gets called on $scope.$eval

Am in the process of converting an angular directive to a react component. One of my component properties is a function (was scope property of & before converting) and when reactDirective loops through the propNames it does a scope.$eval on each property. When this happens the function actually gets executed even though component is not loaded yet and should not execute until it is called by component. Here is a code snippet of my component. Is there another way I should do this?

 onRowSelect:React.PropTypes.func

the attribute in my html

on-row-select="onRowSelected(itemId)"

Does not work with browserify

No matter what it does not work with browserify

I have tried using angular and ngReact from npm and it failed.
Then i tried using http://ngcli.github.io/ , which auto converts bower_components to simple require() statements and it even failed there.

Error message

undefined is not a function on below line.

  return angular.module('react', [])

require("angular") is available to my app so it should be available to ngReact , not sure what is the issue here.

Suggestion: make `reactDirective` more "angular"

From the example in the readme, I'd have expected reactDirective usage to look more like this:

app.directive('hello', function(reactDirective, HelloComponent) {
  return reactDirective(HelloComponent);
});

So that one could also create inline React components like:

app.directive('hello', function() {
    return reactDirective(React.createClass({ ... }));
});

To go a step further, I think it would be a one-cover-all solution to have an extension to Angular modules so that one could write:

app.reactDirective('hello', function(myInjectable) {
    return {
       // This object will be automatically passed to React.createClass
    };
});

Although it is not that easy to add functionalities to Angular modules. So, yet another idea could be:

app.directive('hello', reactDirective(function(myInjectable) {
    return {
       // This object will be automatically passed to React.createClass
    };
}));

I might need to use React in an Angular project soon so I think I'll explore this ideas myself at some point.

Protractor / E2E - How to address ngReact components?

Hello,
I've been working on a project with ngReact glueing angular, React and some more together.

A new challenge I've faced now is how is a good practice to address React Component display / input fields when writing the specs.

May I have your advice?

Regards,
Lourenzo Ferreira

Example with JSX

I am trying to recreate the example with this plunker http://plnkr.co/edit/AXgCNkTiuN6n6WW6J36G. I keep getting

Uncaught ReferenceError: HelloComponent is not defined app.js:8(anonymous function) app.js:8

This seems to be related to the fact that I am using JSX. When I go to the examples section, none of the examples use JSX. This is in contrast to the example in the README.md which does.

Would it be possible to add a JSX example?

standalone react-component distribution

I wanted to start using React components inside an existing angular application and your react-component did the trick for me. However I was only interested in the react-component directive, so I created https://github.com/kasperp/angular-react which is based around your work.

I added support for using angulars DI, so I could reuse existing angular filters and service within my React components like this.

app.filter( 'hero', function() {
  return function( person ) {
    if ( person.fname === 'Clark' && person.lname === 'Kent' ) {
      return 'Superman';
    }
    return person.fname + ' ' + person.lname;
  };
} );

/** @jsx React.DOM */
app.factory( "Hello", function( $filter ) {
  return React.createClass( {
    propTypes: {
      person: React.PropTypes.object.isRequired,
    },
    render: function() {
      return <span>Hello $filter( 'hero' )( this.props.person )</span>;
    }
  } );
} );

Further I added a service for creating named angular directives backed by React components. Something like:

// declare hello directive using the `reactDirective` service.
app.directive( 'hello', function( reactDirective ) {
  return reactDirective( 'Hello' );
} );

Which can then by used in an angular view like this:

<body ng-app="app">
  <h1 ng-controller="helloController">
    <hello fname="person.fname" lname="person.lname"/>
  </h1>
</body> 

Let me know what you think? Is it something you'd be interested in getting in a pull-request, or are you happy with it living else where ?

Question about getting data into react

Hi,
i am very new to react but it seems that it should be the best solution to speed up angularjs when rendering large tables.
I have following table:

<table>
     <tbody ng-repeat="h in event.Heats">
        <react-component name="entrybody" props="h.Entries" />
   </tbody>
</table>

i am sorry for the bad formatting, but i did not find the tag for code.

The renderfunction get called as expected but without data in props, if i say props="event" i get the data. Any idea what i am doing wrong?

Kind Regards Manuel

Sope function with return

I'm new to ng-React and I'm trying to run function from scope in my react component and get the return value from that function. I've managed to run scope function by adding this my view:

<cell get-data="getSomething"/>

And by making this in my react class:

var ReactTableRow = React.createClass({
    propTypes: {
        getData: React.PropTypes.func
    },
    render: function() {
        var foo= this.props.getData(400);
        return (
            React.DOM.div(null, foo)
        )
    }
});

And my controller:

$scope.getSomething = function(number) {
    return number + 10;
}

So, when i debug i can see that my function is being called but the return is not working. Any ideas how to make that possible?

How do you get angular code to compile within the rendered react components?

First off guys, I love what you're doing. Bravo.

But how do you $compile anglarjs code within react components? Say you render a reactComponent within a reactDirective, provided by the ngReact module, that contains angular attributes -- such as ng-click="". How do you get those attributes activated and compiled to work with angular?

Here's some example code that I've been trying to work through that doesn't work. The ng-click never becomes activated, probably because the render is getting executed after the angular controller code is being executed...

Sorry, but here comes a lot of code.

<html>
    <slab-table table="table" />
    <div id=''btntest"></div>
</html>
<script type="text/jsx">
    var num = 4;
        var ngbutton = React.createClass({
            render: function() {
                return (
                    <ng-button type={this.props.type} className={this.props.class} data-ng-click={this.props.ngclick}>
                        {this.props.text}
                    <ng-button>
                );
            }
        });
        var dumpBtn = React.createElement(ngbutton, _.extend({}, this.props, { type: 'button', class: 'btn btn-success', ngclick: 'getTest()', text: 'Dump'}));
        React.render(dumpBtn, document.getElementById('btntest'));
</script>
<script>
var app = angular.module('app', ['react']);
app.value( 'SlabTable', React.createClass( {
    ....
});
app.directive( 'slabTable', function( reactDirective ) {
    return reactDirective( 'SlabTable' );
});
app.directive('ngButton', function($compile) {
    return {
        restrict: 'CAE',
        replace: true,
        link: function(scope, element, attrs) {
            console.log('I was called');
            var html = element.html();
            $compile(element.contents())(scope);
        }
    }
})

app.controller('mainCtrl', function($scope) {
    $http.get('address').then(function(data) {
        var thistable = {
            cols: [ '', 'name', 'chuck_size', 'chunks_per_page', 'get_hits', 'mem_requested', 'total_chunks', 'total_pages', 'used_chunks' ],
            rows: rows
        };
        React.render(React.createElement(SlabTable, _.extend({}, this.props, { table: thistable })),document.getElementById('react'));
    });

    $scope.getTest = function() {
        alert("ng-click worked!");
    }
});
</script>

I think, next I'll try modifying ngReact.js. From lines 143 to 168, within reactComponent, through the link function (https://github.com/davidchang/ngReact/blob/master/ngReact.js#L143-L168). Do you think it would possibly work if I put something in there to replace the given html code with $compileed code?

CommonJs Check Passing Extra Parameter

Line 12:
module.exports = factory(root, require('react'), require('angular'));

Passes an extra parameter to the factory function:
function (React, angular) { return ngReact(React, angular); }

This ends up resulting in React being defined as Angular and Angular being undefined when using CommonJS with ngReact.

Include react main.js file as-is?

I've created a simple react component and included the main.js script in my index.html. It uses Browserify. When I try use it on the page in the native React way (React.render( component, document.querySelector( '.put-it-here')), it can be replaced in the DOM when Angular refreshes a state. That's what brought me here.

Is there a way to keep this main.js file as-is and create a directive from it? I'm getting errors that my components are undefined right now.

None of the examples seem to include another outside file for React code.

I hope this makes sense, I'm new to React.

Using tag in rendering

Hi,
I am new to use this ngReact, so i have a small problem, In your example of table, it is used 'React.DOM.table' kind of tags. Is it possible to render pure tags like

<tr>{ key: i }</tr>

in rendering function because i am trying use this ngReact with angular material tags in order to render a grid view.

Thanks.

this.props.data undefined in ReactComponent

Hi,

I'm invoking the directive like this:

<div ng-react-component="ReactList" data="myItems"></div>

which is the recommended way on docs page.

This is what my ReactComponent code looks like:

window.ReactList = React.createClass({
    render: function() {
        // this.props.data is undefined here
        // this.props.scope.data is undefined here
        // this.props.scope.myItems is a valid collection of items here

        return (
            <ReactListBase scope={this.props.scope} items={this.props.scope.myItems } />
        );
});

the problem is that this.props.scope.data is undefined within the React component and if I understand this correctly, it should contain myItems?

Is this a bug or am I doing something wrong here?

I'm using:
AngularJS v1.2.14
Latest ngReact
ReactJS v0.10.0

Thank you

React templates inside HTML

Can i attach templates in plain html as i do in angular?


<body ng-app="app">
  <div ng-controller="helloController">
    <react-component component-name="Hello" props="person">
       <span>hello {this.props.person}</span>
    </react-component>
  </div>
</body>

Dynamically changing rowSpan

I have a problem when trying to update my table. This is how my initial table looks like:

Image of initial table

So the rowspan here works fine. My "Row" table cell looks like this:

<th className="rotate header" rowSpan={this.props.tableFoo.axisY.ordinates.length}><div><span>Row</span></div></th>

So I'm looking for the length of ordinates array for axis Y and that is the number of rows which I want my "Row" cell to cover.
Then on "Add new Y ordinate" click this is fired:

$scope.addNewYOrdinate = function() {
            $scope.tableFoo.axisY.ordinates.push({
                id: 12348,
                label: "Ordinate Y 4"
            });
};

The ract table re-renders because the props has changed and this is what I get in result:
Image of final table

So for some reason, although the rowspan changes to 4 and I can see that when inspecting elements, the actual rowspan still remains 3. Why is that? Is it a bug?

reactComponent and controllerAs

the react component does not work with controllerAs structure. The reason being if you have this in your html: props="home.config" then reactComponent does this scope[attrs.props] which comes back as undefined. Are there any plans to support controllerAs or are you aware of a work around?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.