Pregunta

Estoy usando UI-Router en un proyecto AngularJS donde tengo una vista anidada que contiene una directiva personalizada. Esta directiva hace que un campo de entrada (vamos a decir un campo de filtro) y su valor debe estar sincronizado con el alcance del controlador.


Esto funciona bien para esta directiva, cuando la vista / estado no está anidado:

jsfiddle / no anidado / funcionando como se espera

var myApp = angular.module('myApp', ['ui.router', 'myComponents'])
    .config(['$stateProvider', function ($stateProvider) {
        $stateProvider.
            state('home', {
                url: '',
                template: '<my-filter text-filter="theFilter"></my-filter><button ng-click="inspect()">inspect</button>{{ theFilter |json}}',
                controller: 'myController'
            });
    }]);

var components = angular.module('myComponents', []);

components.directive('myFilter', [function () {
    return {
        restrict: 'E',
        template: '<input type="text" name="filter" ng-model="textFilter">',
        scope: {
            textFilter: '='
        }
    };
}]);

components.controller('myController', ['$scope', function ($scope) {
    $scope.theFilter = 'initial filter';

    $scope.inspect = function () {
        alert($scope.theFilter);
    }
}]);

Ver:

<div ng-app="myApp">
    <div ui-View></div>
</div>

Cuando cambio el texto del campo de entrada, se refleja en el alcance ...


... pero cuando anidé la vista / estado, el valor en el alcance mantiene su valor inicial, pero espero que se cambie de acuerdo con el valor del campo de entrada cuando se sobrescribe.

var myApp = angular.module('myApp', ['ui.router', 'myComponents'])
    .config(['$stateProvider', function ($stateProvider) {
        $stateProvider.
            state('home', {
                abstract: true,
                url: '',
                template: 'Nested View:<div ui-view></div>',
                controller: 'myController'
            }).
            state('home.detail', {
                url: '',
                template: '<my-filter text-filter="theFilter"></my-filter><button ng-click="inspect()">inspect</button>{{ theFilter |json}}'
            });;
    }]);


var components = angular.module('myComponents', []);

components.directive('myFilter', [function () {
    return {
        restrict: 'E',
        template: '<input type="text" name="filter" ng-model="textFilter">',
        scope: {
            textFilter: '='
        }
    };
}]);

components.controller('myController', ['$scope', function ($scope) {
    $scope.theFilter = 'initial filter';

    $scope.inspect = function () {
        alert($scope.theFilter);
    }
}]);

Ver:

<div ng-app="myApp" >
    <div ui-View></div>
</div>

Aquí, el texto en el alcance (ver controlador) sigue siendo el mismo.

¿Alguna idea de cómo puedo obtener el mismo resultado con vistas anidadas como en el primer ejemplo?

PS: La Directiva debe permanecer reutilizable

jsfiddle / anidado / no funciona como se espera

¿Fue útil?

Solución

Esto está relacionado con un problema común.Como se mencionó en este video angular js - la mejor práctica (29:19), y explicó aquí: Scopes anidados en JS angular

"Siempre que tenga un modelo de NG, hay que ser un punto en alguna parte. Si no tiene un punto, lo está haciendo mal".

Por lo tanto, el controlador debe estar creando un objeto:

components.controller('myController', ['$scope', function($scope) {

    // here theFilter is an object
    // with property value
    $scope.theFilter =  { value : 'initial filter'};

    $scope.inspect = function() {
        alert($scope.theFilter.value);
    }    
}]);

y la plantilla debe trabajar con un objeto que tiene propiedad value:

components.directive('myFilter', [function() {
    return {
        restrict: 'E',
        template: '<input type="text" name="filter" ng-model="textFilter.value">',
        scope: {
            textFilter: '='             
        }
    };          
}]);

The upated jsfiddle

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top