简体   繁体   中英

How to have AngularJS 1.6 call a function a single time when the user updates an input

I've written some AngularJS code that allows the user to enter some numbers into some inputs in a browser and then see lines drawn on an svg element in response.

The svg element has a number of child line elements. Each one has attributes x1, x2, y1, y2, and style. Each one of these attributes has a computed value. Each computed value is a property of an object that is returned from a Javascript function. That means that the Javascript function is called five times : once for each attribute of each line.

In order to unclutter my display code and improve performance, I wrote a Javascript function that returns an array of objects with each objects containing the values for the attributes x1, x2, y1, y2, and style of a single line element. I thought it was a simple and reasonable solution.

My code now looks like this:

<line ng-repeat="line in getLines()" x1="{{line.x1}}" x2="{{line.x2}}
      y1="{{line.y1}}" y2="{{line.y2}}" ng-style="line.style" />

When I run this code, I get an AngularJS infdig error, indicating that the model would be computed an infinite number of times. I checked the documentation for this error: https://docs.angularjs.org/error/$rootScope/infdig

It says: One common mistake is binding to a function which generates a new array every time it is called.... The solution is to return the same array object if the elements have not changed.

That last part doesn't help at all because the contents of that array do, indeed, change with every number entered into the form.

I feel like I'm doing something to make this harder than it should be.

What I want is that when the user modifies one or more numbers in the input fields, the function getLines should be called a single time and the results should be used to populate the attributes of various line elements so that the user can see lines in the browser.

How do I make sure that getLines is called a single time when the inptu fields are updated?

What I would do is:

Inputs:

<input id="x1" type="text" ng-change="changeHandler(elem)"/>
.
.
<input id="y2" type="text" ng-change="changeHandler(elem)"/>

Handlers:

function changeHandler(elem) {

    //Get value from event
    if (elem.id = 'x1')

        if (line.x1 != elem.value) {
            //Call function to update svg
            applyChange(line)
        }
    //.
    //.
    //.
    else if (elem.id = 'y2')

        if (line.y2 != elem.value) {
            applyChange(line)
        }


}

I am not sure if elem.value and elem.id is de right thing, you will have to do it but it does exist.

I'm not sure I understand what getLines is doing. But I think you should try to store the lines values in an object, and use that object for the ng-repeat instead of the function. And use ngChange to trigger an event when an field is modified.

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