角度指令和范围更新让人疯狂

Getting crazy with angular directive and scope update

本文关键字:疯狂 更新 范围 指令      更新时间:2023-09-26

我已经试了7个小时来做一些工作了,现在我正在全力以赴
难以置信

我只想从一个独立的指令中更新一个控制器变量
疯狂的是,在这种观点中,一切都很完美,但在控制器中,他没有意识到变化!

控制器看起来是这样的,因为它是由TypeScript生成的。

/*
ANGULAR CONTROLLER
*/
var CustomerdataTabCtrl = (function () {
    function CustomerdataTabCtrl($scope) {
        $scope.AddressAutocompleteOptions = {};
        $scope.AddressAutocompleteOptions.watchEnter = true;
        $scope.AddressAutocompleteDetails = '';
        $scope.AddressAutocompleteAddress = null;
        $scope.onRoleChange = function () {
            if ($scope.Role == 'Provider') {
                $('#orders-tab-header').css('display', 'none');
            } else {
                $('#orders-tab-header').css('display', 'block');
            }
        };
        $scope.onAddressAutocompleteChange = function () {
            alert('asd');
        };
        $scope.$watch('Role', function () {
            return $scope.onRoleChange();
        }, true);
        $scope.$watch('AddressAutocompleteAddress', function () {
            return $scope.onAddressAutocompleteChange();
        }, true);
    }
    return CustomerdataTabCtrl;
})();
/*
ANGULAR DIRECTIVE
*/
angular.module("ngAutocomplete", [])
    .directive('ngAutocomplete', function () {
        return {
            require: 'ngModel',
            scope: {
                ngModel: '=',
                options: '=',
                details: '=',
                address: '='
            },
            link: function (scope, element, attrs, controller) {
                //options for autocomplete
                var opts;
                var watchEnter = false;
                //convert options provided to opts
                var initOpts = function () {
                    opts = {};
                    if (scope.options) {
                        if (scope.options.watchEnter !== true) {
                            watchEnter = false
                        } else {
                            watchEnter = true
                        }
                        if (scope.options.types) {
                            opts.types = [];
                            opts.types.push(scope.options.types);
                            scope.gPlace.setTypes(opts.types)
                        } else {
                            scope.gPlace.setTypes([])
                        }
                        if (scope.options.bounds) {
                            opts.bounds = scope.options.bounds;
                            scope.gPlace.setBounds(opts.bounds)
                        } else {
                            scope.gPlace.setBounds(null)
                        }
                        if (scope.options.country) {
                            opts.componentRestrictions = {
                                country: scope.options.country
                            };
                            scope.gPlace.setComponentRestrictions(opts.componentRestrictions);
                        } else {
                            scope.gPlace.setComponentRestrictions(null);
                        }
                    }
                };
                if (scope.gPlace == undefined) {
                    scope.gPlace = new google.maps.places.Autocomplete(element[0], {});
                }
                google.maps.event.addListener(scope.gPlace, 'place_changed', function () {
                    var result = scope.gPlace.getPlace();
                    if (result !== undefined) {
                        if (result.address_components !== undefined) {
                            scope.$apply(function () {
                                scope.address = parseGoogleResponse(result.address_components);
                                scope.details = result;
                                controller.$setViewValue(element.val());
                            });
                        }
                        else {
                            if (watchEnter) {
                                getPlace(result)
                            }
                        }
                    }
                });
                //function to get retrieve the autocompletes first result using the AutocompleteService
                var getPlace = function (result) {
                    ...                    
                };

                var parseGoogleResponse = function(components) {
                    var result = {};
                    for (var i = 0; i < components.length; i++) {
                        var addressType = components[i].types[0];
                        result[addressType] = components[i]['long_name'];
                    }
                    return result;
                };

                controller.$render = function () {
                    var location = controller.$viewValue;
                    element.val(location);
                };
                //watch options provided to directive
                scope.watchOptions = function () {
                    return scope.options
                };
                scope.$watch(scope.watchOptions, function () {
                    initOpts()
                }, true);
            }
        };
    });

HTML

<div ng-controller="CustomerdataTabCtrl">
<input type="text" id="customerdata_quick_auto_address" name="customerdata_quick_auto_address" class="form-control input-sm" ng-autocomplete ng-model="AddressAutocomplete" options="AddressAutocompleteOptions" details="AddressAutocompleteDetails" address="AddressAutocompleteAddress" />
{{AddressAutocompleteAddress.route}}
</div>

就像我说的,视图输出正确的结果,但控制器手表只在init上启动一次,但再也不会启动,但它是相同的fu。。。。变量视图{{AddressAutocompleteAddress.route}}使用控制器作用域变量,我真的疯了!

亲切问候

正如我在评论中提到的,这是变量作用域的问题。该指令的隔离作用域使其成为AddressAutocompleteAddress变量的自己的实例,因为它是一个"基元"变量。解决此问题的方法是使用"."(点)表示法。

我可能会对您的代码做的是创建一个名为AddressAutocomplete的对象,然后将其他变量添加到该对象中。

function CustomerdataTabCtrl($scope) {
    $scope.AddressAutocomplete = {};
    $scope.AddressAutocomplete.Text = '';
    $scope.AddressAutocomplete.Options = {};
    $scope.AddressAutocomplete.Options.watchEnter = true;
    $scope.AddressAutocomplete.Details = '';
    $scope.AddressAutocomplete.Address = null;
    ...
}

在你的html:

<div ng-controller="CustomerdataTabCtrl">
    <input type="text" id="customerdata_quick_auto_address" 
       name="customerdata_quick_auto_address"
       class="form-control input-sm" ng-model="AddressAutocomplete.Text" 
       ng-autocomplete options="AddressAutocomplete.Options"
       details="AddressAutocomplete.Details" address="AddressAutocomplete.Address" />
    {{AddressAutocomplete.Address.route}}
</div>

只需记住更新您在控制器中使用变量的方式。此外,我看不出你在指令中在哪里使用ng-model变量,所以我不确定你为什么在那里使用它。

还有一件事,您真的不应该为指令使用ng-前缀,这是AngularJs库中指令的保留前缀。