简体   繁体   中英

Why is there no binding between React.Js template and Angular model?

I am trying to mix Angular and React.JS. You can see my code here . Most examples I have seen involve an input written in basic Angular, and then output written in React like in this example . I am trying to do the opposite. I have two input fields as React components created in a directive and then an output of the model done with Angular.

I cannot get the output to reflect changes in the model. The model being $scope.formData = {name: "name", email: "email"};

I tried to follow the example in this video , and create an isolated scope in the directive

scope: {
            formname: '=formname',
            formemail:'=formemail'
        },

and then pass the proper values through to the React template. It doesn't seem to have any affect. My input is not connected to the formData. In my non-React version of this, the model data fills in the input immediately and the output reflects changes to the input.

Because binding that data in an Angular style is breaking, I tried to have the React components update the model in a more Reactish way. I wrote a function in the controller called update_model,

$scope.update_model = function(data_type, updated_data){
                $scope.$apply(function() {
                    $scope.formData[data_type] = updated_data;
                });
                console.log($scope.formData);
            }

I then passed that function through the directive to the React template using scope.update_model, in the link function.

link: function(scope, element) {
        React.renderComponent(Form_Profile_Component({update_model: scope.update_model, name_label: 'name', email_label: 'email', name_data: scope.formname, email_data: scope.formemail}), element[0]);
    }

Now in the template, the input elements have and onChange event detector that will call this, and update the Model. The Model is supposed to be displayed at the bottom of the page with

    <pre>
        {{ formData }}
    </pre>

The console.log shows a change in formData, but the {{formData}} display does not change.

Why won't my display {{formData}} show what is going on in the actual formData object?

EDIT: Just to make sure there wasn't a problem with {formData} I threw <input ng-model="formData.name"> in a few places in form.html, and there was no problem. The two way binding worked there.

EDIT 2: I tried adding the code below to the directive.

link: function(scope, element) {
            scope.$watch('formData.name', function(newVal, oldVal) {
              console.log("---");
              React.renderComponent(Form_Profile_Component({update_model: scope.update_model, name_label: 'name', email_label: 'email', name_data: scope.formData.name, email_data: scope.formData.email}), element[0]);
            });
        }

I believe that when there is a change in formData, it will call this function and update the React component, or at the very least print '---' to the console. When I use the React input or the proper input nothing happens, which is not so surprising at this point. But when I tried the working input from the first edit, which does alter {{formData}} , nothing happens. It doesn't trigger the watch at all, I don't understand why.

You're on the right track with your 2nd edit where you put the renderComponent call inside a scope.$watch . This will make sure that the react component is re-rendered every time your watch variable formData.name changes.

However if you're looking for the changes you make within your React Component to propagate back out to angular, you need to make sure that the callback function you're passing to react has scope.$apply() call in it. Either encapsulating the change, or just after it.

Here's a quick example:

In your controller:

$scope.myVar  = 'foo';
$scope.setVar = function(value) {
    $scope.myVar = value;
    $scope.$apply();
};

In your directive's link function (assuming no restricted scope, else change name as needed)

scope.$watch('myVar', function() {
    React.renderComponent(
        MyComponent({
            myVar:  scope.myVar,
            setVar: scope.setVar
        }),
        element.get(0)
    );
});

Then just call the this.props.setVar function from within your react component with the new value and it'll update correctly on the model.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM