使用具有相同控制器的多个模板更新$ scope

时间:2021-09-21 11:17:22

I have the following route:

我有以下路线:

.state('cloud', {
    url: '/cloud',
    views: { 
        'main': { templateUrl: 'pages/templates/cloud.html', controller: 'cloud' },
        'choices-header': { templateUrl: 'pages/templates/views/choices-header.html', controller: 'cloud' }
    }
})

I do this because I need my choices-header template to go into a different view then my main template.

我这样做是因为我需要我的选择 - 标题模板进入与我的主模板不同的视图。

#options_header in my choices-header template is supposed to show if $scope.cloud_selected_items has items in it.

我的choices-header模板中的#options_header应该显示$ scope.cloud_selected_items中是否包含项目。

But for some reason, when an item is added to the array, it doesn't know this, so the element doesn't show. However if I reload the page with an item in the array, it will show. So I know that the code is working.

但由于某种原因,当一个项目被添加到数组时,它不知道这一点,因此该元素不会显示。但是,如果我使用数组中的项重新加载页面,它将显示。所以我知道代码正在运行。

Does anyone know what I need to do with my cloudCheck() function so that the scope updates and my template see's the change in my $scope?

有谁知道我需要用我的cloudCheck()函数做什么,以便范围更新和我的模板看到我的$ scope的变化?

So in my index page, I have:

所以在我的索引页面中,我有:

<div ui-view="choices-header"></div>
<div id="pageContent">
    <div ui-view="main"></div>
</div>

cloud.html

<div ng-repeat="data in items">
   <div ng-click="cloudCheck(data.id)">Click me</div>
</div>

choices_header.html

<div id="option-header" ng-show="cloud_selected_items.length > 0">
    {{ cloud_selected_items.length }} selected
</div>

javascript

.controller('cloud', function($scope, $rootScope, $http, $state, $stateParams) {
    $scope.cloud_selected_items = [];

    $scope.cloudCheck = function(id) {
        $scope.cloud_selected_items.push(id);
    }
}

1 个解决方案

#1


1  

I think the problem with your code is that the scope is not shared in your views. Scope will be inherited in nested views but you're having two separate views.

我认为您的代码存在的问题是您的视图中不会共享范围。范围将在嵌套视图中继承,但您有两个单独的视图。

If you do console.log($scope) you'll see that cloud controller will run twice with different scopes. You can see that scopes are different by the scope property $id.

如果您执行console.log($ scope),您将看到云控制器将以不同的范围运行两次。您可以通过scope属性$ id看到范围不同。

You can use a service that keeps track of your selected items. Then the two-way binding will update your header view as expected.

您可以使用跟踪所选项目的服务。然后双向绑定将按预期更新标题视图。

Please see code below (not working here, cookie issue with ui-router on SO) and here a working demo at jsFiddle.

请参阅下面的代码(不在这里工作,在o上使用ui-router的cookie问题),这里是jsFiddle的工作演示。

angular.module('myApp', ['ui.router'])
    .controller('cloud', function ($scope, $state, cloudService) {
        $scope.items = [{
            id: 1,
            data: 'test1'
        },
        {
            id: 2,
            data: 'test2'
        },
        {
            id: 2,
            data: 'test2'
        }]; //dummy data
        $scope.cloud_selected_items = cloudService.getItems();
        
        $scope.cloudCheck = cloudService.cloudCheck;
        /*function(item) {
            console.log(id);
            $scope.cloud_selected_items.push(item);
        };*/
})
.factory('cloudService', function() {
    var cloudSelectedItems = [];
    
    var cloudService = {
        cloudCheck: function(item) {
            cloudSelectedItems.push(item);
        },
        getItems: function() {
            return cloudSelectedItems;
        }
    };
    
    return cloudService;
})
.config(function ($stateProvider, $urlRouterProvider) {
    //
    // For any unmatched url, redirect to /state1
    $urlRouterProvider.otherwise("/cloud");
    //
    // Now set up the states
    $stateProvider.state('cloud', {
        url: '/cloud',
        views: { 
            'main': {
                templateUrl: 'partials/cloud.html', controller: 'cloud' 
            },
            'choicesheader': { 
                templateUrl: 'partials/choices_header.html', 
                controller: 'cloud' 
            }
        }
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.14/angular-ui-router.min.js"></script>

<script type="text/ng-template" id="partials/choices_header.html">
    <div id="option-header" ng-show="cloud_selected_items.length > 0">
    {{ cloud_selected_items.length }} selected
</div>
</script>

<script type="text/ng-template" id="partials/cloud.html">
    <div ng-repeat="data in items">
        <button ng-click="cloudCheck(data.id)">Click me</button>
    </div>
</script>

<div ng-app="myApp">
  <div ui-view="choicesheader"></div>
  <div id="pageContent">
    <div ui-view="main"></div>
  </div>
</div>

#1


1  

I think the problem with your code is that the scope is not shared in your views. Scope will be inherited in nested views but you're having two separate views.

我认为您的代码存在的问题是您的视图中不会共享范围。范围将在嵌套视图中继承,但您有两个单独的视图。

If you do console.log($scope) you'll see that cloud controller will run twice with different scopes. You can see that scopes are different by the scope property $id.

如果您执行console.log($ scope),您将看到云控制器将以不同的范围运行两次。您可以通过scope属性$ id看到范围不同。

You can use a service that keeps track of your selected items. Then the two-way binding will update your header view as expected.

您可以使用跟踪所选项目的服务。然后双向绑定将按预期更新标题视图。

Please see code below (not working here, cookie issue with ui-router on SO) and here a working demo at jsFiddle.

请参阅下面的代码(不在这里工作,在o上使用ui-router的cookie问题),这里是jsFiddle的工作演示。

angular.module('myApp', ['ui.router'])
    .controller('cloud', function ($scope, $state, cloudService) {
        $scope.items = [{
            id: 1,
            data: 'test1'
        },
        {
            id: 2,
            data: 'test2'
        },
        {
            id: 2,
            data: 'test2'
        }]; //dummy data
        $scope.cloud_selected_items = cloudService.getItems();
        
        $scope.cloudCheck = cloudService.cloudCheck;
        /*function(item) {
            console.log(id);
            $scope.cloud_selected_items.push(item);
        };*/
})
.factory('cloudService', function() {
    var cloudSelectedItems = [];
    
    var cloudService = {
        cloudCheck: function(item) {
            cloudSelectedItems.push(item);
        },
        getItems: function() {
            return cloudSelectedItems;
        }
    };
    
    return cloudService;
})
.config(function ($stateProvider, $urlRouterProvider) {
    //
    // For any unmatched url, redirect to /state1
    $urlRouterProvider.otherwise("/cloud");
    //
    // Now set up the states
    $stateProvider.state('cloud', {
        url: '/cloud',
        views: { 
            'main': {
                templateUrl: 'partials/cloud.html', controller: 'cloud' 
            },
            'choicesheader': { 
                templateUrl: 'partials/choices_header.html', 
                controller: 'cloud' 
            }
        }
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.14/angular-ui-router.min.js"></script>

<script type="text/ng-template" id="partials/choices_header.html">
    <div id="option-header" ng-show="cloud_selected_items.length > 0">
    {{ cloud_selected_items.length }} selected
</div>
</script>

<script type="text/ng-template" id="partials/cloud.html">
    <div ng-repeat="data in items">
        <button ng-click="cloudCheck(data.id)">Click me</button>
    </div>
</script>

<div ng-app="myApp">
  <div ui-view="choicesheader"></div>
  <div id="pageContent">
    <div ui-view="main"></div>
  </div>
</div>