আপনি কৌনিক জেএস এ নিয়ন্ত্রণকারী পুনরায় লোড না করে কোনও পথ পরিবর্তন করতে পারেন?


191

এটি আগে জিজ্ঞাসা করা হয়েছিল, এবং উত্তরগুলি থেকে এটি ভাল দেখাচ্ছে না। আমি এই নমুনা কোডটি বিবেচনায় রেখে জিজ্ঞাসা করতে চাই ...

আমার অ্যাপ্লিকেশনটি সরবরাহ করে এমন পরিষেবাতে বর্তমান আইটেমটি লোড করে। এমন বেশ কয়েকটি নিয়ন্ত্রণকারী রয়েছে যা আইটেমটি পুনরায় লোড না করে আইটেমের ডেটা ম্যানিপুলেট করে।

আমার কন্ট্রোলাররা আইটেমটি এখনও সেট না করা থাকলে এটি পুনরায় লোড করবে, অন্যথায়, এটি পরিষেবা থেকে বর্তমানে লোড হওয়া আইটেমটি নিয়ন্ত্রণকারীদের মধ্যে ব্যবহার করবে।

সমস্যা : আমি আইটেম এইচটিএমএল লোড না করে প্রতিটি নিয়ামকের জন্য পৃথক পাথ ব্যবহার করতে চাই।

1) এটা সম্ভব?

২) যদি এটি সম্ভব না হয় তবে আমি এখানে যা এসেছি তার চেয়ে নিয়ামক প্রতি পাথের চেয়ে আরও ভাল উপায় থাকতে পারে?

app.js

var app = angular.module('myModule', []).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
      when('/items', {templateUrl: 'partials/items.html',   controller: ItemsCtrl}).
      when('/items/:itemId/foo', {templateUrl: 'partials/item.html', controller: ItemFooCtrl}).
      when('/items/:itemId/bar', {templateUrl: 'partials/item.html', controller: ItemBarCtrl}).
      otherwise({redirectTo: '/items'});
    }]);

Item.html

<!-- Menu -->
<a id="fooTab" my-active-directive="view.name" href="#/item/{{item.id}}/foo">Foo</a>
<a id="barTab" my-active-directive="view.name" href="#/item/{{item.id}}/bar">Bar</a>
<!-- Content -->
<div class="content" ng-include="" src="view.template"></div>

controller.js

// Helper function to load $scope.item if refresh or directly linked
function itemCtrlInit($scope, $routeParams, MyService) {
  $scope.item = MyService.currentItem;
  if (!$scope.item) {
    MyService.currentItem = MyService.get({itemId: $routeParams.itemId});
    $scope.item = MyService.currentItem;
  }
}
function itemFooCtrl($scope, $routeParams, MyService) {
  $scope.view = {name: 'foo', template: 'partials/itemFoo.html'};
  itemCtrlInit($scope, $routeParams, MyService);
}
function itemBarCtrl($scope, $routeParams, MyService) {
  $scope.view = {name: 'bar', template: 'partials/itemBar.html'};
  itemCtrlInit($scope, $routeParams, MyService);
}

রেজোলিউশন।

স্থিতি : গৃহীত উত্তরে প্রস্তাবিত অনুসারে অনুসন্ধান কোয়েরিটি ব্যবহার করে আমাকে প্রধান নিয়ামককে পুনরায় লোড না করে বিভিন্ন ইউআরএল সরবরাহ করার অনুমতি দেয়।

app.js

var app = angular.module('myModule', []).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
      when('/items', {templateUrl: 'partials/items.html',   controller: ItemsCtrl}).
      when('/item/:itemId/', {templateUrl: 'partials/item.html', controller: ItemCtrl, reloadOnSearch: false}).
      otherwise({redirectTo: '/items'});
    }]);

Item.html

<!-- Menu -->
<dd id="fooTab" item-tab="view.name" ng-click="view = views.foo;"><a href="#/item/{{item.id}}/?view=foo">Foo</a></dd>
<dd id="barTab" item-tab="view.name" ng-click="view = views.bar;"><a href="#/item/{{item.id}}/?view=foo">Bar</a></dd>

<!-- Content -->
<div class="content" ng-include="" src="view.template"></div>

controller.js

function ItemCtrl($scope, $routeParams, Appts) {
  $scope.views = {
    foo: {name: 'foo', template: 'partials/itemFoo.html'},
    bar: {name: 'bar', template: 'partials/itemBar.html'},
  }
  $scope.view = $scope.views[$routeParams.view];
}

directives.js

app.directive('itemTab', function(){
  return function(scope, elem, attrs) {
    scope.$watch(attrs.itemTab, function(val) {
      if (val+'Tab' == attrs.id) {
        elem.addClass('active');
      } else {
        elem.removeClass('active');
      }
    });
  }
});

আমার পার্টিশালের ভিতরে থাকা সামগ্রীটি মোড়ানো রয়েছে ng-controller=...


এই উত্তরটি পাওয়া যায়নি: stackoverflow.com/a/18551525/632088 - এটা reloadOnSearch ব্যবহার করে: মিথ্যা, কিন্তু এটা searchbar URL টি আপডেট (যেমন ব্যবহারকারী ক্লিক ব্যাক যদি বোতাম & url টি পরিবর্তন) জন্য চেক
রবার্ট রাজা

উত্তর:


115

তোমার মত পাসওয়ার্ড ব্যবহার করতে না থাকে তাহলে #/item/{{item.id}}/foo#/item/{{item.id}}/barকিন্তু #/item/{{item.id}}/?foo#/item/{{item.id}}/?barপরিবর্তে, আপনার জন্য আপনার রুট সেট আপ করতে পারেন /item/{{item.id}}/আছে reloadOnSearchসেট false( https://docs.angularjs.org/api/ngRoute/provider/$routeProvider )। এটি অ্যাঙ্গুলারজেএসকে ইউআরএলটির অনুসন্ধানের অংশটি পরিবর্তিত হলে ভিউটি পুনরায় লোড না করতে বলে।


তার জন্য ধন্যবাদ. আমি তখন কন্ট্রোলারটি কোথায় পরিবর্তন করব তা জানার চেষ্টা করছি।
কোডার 1

বুঝেছি. আমার দেখার অ্যারেতে একটি নিয়ামক পরম যুক্ত ng-controller="view.controller"হয়েছে , তারপরে ng-includeনির্দেশিকায় যুক্ত হয়েছে ।
কোডার 1

আপনি আইটেমটিসিআরটিআইনেট-এ। লোকেশন.সার্চ () এ একটি ঘড়ি তৈরি করতে এবং অনুসন্ধান প্যারামিটারের উপর নির্ভর করে আপডেট $ স্কোপ.ভিউ.টিম্প্লেট করুন। এবং তারপরে template টেমপ্লেটগুলিকে এমন কিছু দিয়ে মুড়িয়ে দেওয়া যেতে পারে <div ng-controller="itemFooCtrl">... your template content...</div>। সম্পাদনা: আপনার সমাধান হয়েছে দেখে ভাল লাগল, আপনি কীভাবে সমাধান করেছেন সে সম্পর্কে আপনার প্রশ্নটি আপডেট করে দিলে দুর্দান্ত হবে, সম্ভবত জেএসফিডাল দিয়ে।
অ্যান্ডার্স একদাহল

আমি যখন 100% থাকি তখন আমি এটি আপডেট করব। চাইল্ড কন্ট্রোলার এবং এনজি-ক্লিকগুলিতে আমার স্কোপ নিয়ে কিছু গণ্ডগোল হচ্ছে। আমি যদি সরাসরি foo থেকে লোড করি তবে এনজি-ক্লিকগুলি ফু-র স্কোপের মধ্যেই সম্পাদন করে। আমি তারপরে বারে ক্লিক করি এবং সেই টেমপ্লেটের এনজি-ক্লিকগুলি প্যারেন্ট স্কোপে কার্যকর করা হয়।
কোডার 1

1
আপনার অবশ্যই আপনার ইউআরএলস পুনরায় ফর্ম্যাট করার প্রয়োজন নেই তা লক্ষ করা উচিত। পুনরায় বিবাদ পোস্ট করার সময় এটি হতে পারে, তবে ডকুমেন্টেশন ( docs.angularjs.org/api/ngRoute.$routeProvider ) এখন বলেছে: [পুনরায় লোড করুনসার্চ = সত্য] - $ বুলিয়ান =} - কেবল $ অবস্থানের সময় পুনরায় লোড করুন। () বা $ অবস্থান.hash () পরিবর্তনগুলি অনুসন্ধান করুন।
রাইস ভ্যান ডের ওয়েয়ারডেন

93

আপনার যদি পথ পরিবর্তন করার প্রয়োজন হয় তবে আপনার অ্যাপ্লিকেশন ফাইলে আপনার .config এর পরে এটি যুক্ত করুন। তারপরে আপনি আবার $location.path('/sampleurl', false);লোড হওয়া রোধ করতে পারেন

app.run(['$route', '$rootScope', '$location', function ($route, $rootScope, $location) {
    var original = $location.path;
    $location.path = function (path, reload) {
        if (reload === false) {
            var lastRoute = $route.current;
            var un = $rootScope.$on('$locationChangeSuccess', function () {
                $route.current = lastRoute;
                un();
            });
        }
        return original.apply($location, [path]);
    };
}])

আমি খুঁজে পেয়েছি সবচেয়ে মার্জিত সমাধানের জন্য ক্রেডিট https://www.consolelog.io/angularjs-change-path-without-reloading- এ যায়।


6
দুর্দান্ত সমাধান। এটি "সম্মান" করার জন্য ব্রাউজারের পিছনের বোতামটি পাওয়া যায় কি?
মার্ক বি

6
সচেতন হোন যে এই সমাধানটি পুরানো রুটকে রাখে, এবং আপনি যদি $ রুটকন্টেন্টের জন্য জিজ্ঞাসা করেন তবে আপনি পূর্বের পাথটি পাবেন, বর্তমানটি নয়। অন্যথায় এটি দুর্দান্ত হ্যাক hack
জর্নারে

4
কেবল এটিই বলতে চেয়েছিলেন যে আসল সমাধানটি এখানে "ইভানওয়ানস্তলি" দ্বারা নিখুঁতভাবে পোস্ট করা হয়েছিল: github.com/angular/angular.js/issues/1699#issuecomment-34841248
চিপিট 24

2
আমি এই সমাধানটি কিছুক্ষণ ব্যবহার করে চলেছি এবং কেবল লক্ষ্য করেছি যে কিছু পথে পরিবর্তনের সাথে সাথে, সত্য মানটি পাস হয়ে গেলেও পুনরায় লোডগুলি নিবন্ধভুক্ত করে। অন্য কারও মতো সমস্যা আছে কি?
হিচকক

2
আমাকে $timeout(un, 200);রিটার্নের স্টেটমেন্টের আগে যোগ করতে হয়েছিল কারণ কখনও কখনও $locationChangeSuccessআগুন জ্বলে না apply(এবং সত্যই প্রয়োজনের সময় রুট পরিবর্তন করা হয়নি)। আমার সমাধান পথের
অনুরোধের

17

কেন কেবল এনজি-কন্ট্রোলারকে এক স্তর উচ্চতর রাখবেন না,

<body ng-controller="ProjectController">
    <div ng-view><div>

এবং রুটে নিয়ামক স্থাপন করবেন না,

.when('/', { templateUrl: "abc.html" })

এটা আমার জন্য কাজ করে.


দুর্দান্ত টিপ, এটি আমার দৃশ্যের জন্যও পুরোপুরি কাজ করে! আপনাকে অনেক ধন্যবাদ! :)
ডেভনকোড

4
এটি একটি দুর্দান্ত "রাশিয়ানরা পেনসিল ব্যবহার করেছেন" উত্তর, আমার জন্য কাজ করে :)
ইনোলাস্কো

1
আমি খুব শীঘ্রই কথা বললাম। এই কর্মক্ষেত্রে সমস্যা রয়েছে যে আপনি যদি নিয়ামকটিতে $ রুটপ্যারামগুলি থেকে মানগুলি লোড করতে চান তবে সেগুলি লোড হবে না, ডিফল্ট {} এ হবে
inolasco

@ আইনলাস্কো: আপনি যদি আপনার $ রুটপ্যারামগুলি $ রুট চেঞ্জসুসেস হ্যান্ডলারে পড়ে থাকেন তবে কাজ করে। না প্রায়শই, আপনি সম্ভবত যাইহোক এটি চান। কেবলমাত্র নিয়ামকটিতে পড়া আপনাকে মূলত বোঝানো URL টির মান দেয় ally
plong0

@ plong0 ভাল পয়েন্ট, কাজ করা উচিত। যদিও আমার ক্ষেত্রে, যখন নিয়ামক পৃষ্ঠা লোডের উপর চাপ দেয় তখন নির্দিষ্ট মানগুলি আরম্ভ করার জন্য আমার কেবলমাত্র URL মানগুলি পাওয়া দরকার to আমি ভিজরন্ডের প্রস্তাবিত সমাধানটি $ লোকেশনচেনজস্যাক্সেস ব্যবহার করে শেষ করেছি, তবে আপনার পাশাপাশি আরও একটি বৈধ বিকল্প।
inolasco

12

নিয়ন্ত্রক পুনরায় লোড ছাড়াই যাদের পাথ () পরিবর্তনের প্রয়োজন তাদের জন্য - এখানে প্লাগইন রয়েছে: https://github.com/anglibs/angular-location-update

ব্যবহার:

$location.update_path('/notes/1');

Https://stackoverflow.com/a/24102139/1751321 এর উপর ভিত্তি করে

PS এই সমাধানটি https://stackoverflow.com/a/24102139/1751321 এ পাথের পরে বাগ রয়েছে (, মিথ্যা) বলা হয় - এটি ব্রাউজারের নেভিগেশনটি ভেঙে পিছনে / এগিয়ে যাবে যতক্ষণ না পথ (, সত্য) বলা হয়


10

যদিও এই পোস্টটি পুরানো এবং এর একটি উত্তর গৃহীত হয়েছে, রিলোডঅনসেক = ভুয়া ব্যবহার করে আমাদের মধ্যে যাদের সমস্যা নেই কেবল তাদের সত্যিকারের পথ পরিবর্তন করতে হবে এবং কেবল প্যারামগুলি নয়। এখানে বিবেচনা করার জন্য একটি সহজ সমাধান:

এনজি-ভিউয়ের পরিবর্তে এনজি-অন্তর্ভুক্ত ব্যবহার করুন এবং টেমপ্লেটে আপনার নিয়ামককে বরাদ্দ করুন।

<!-- In your index.html - instead of using ng-view -->
<div ng-include="templateUrl"></div>

<!-- In your template specified by app.config -->
<div ng-controller="MyController">{{variableInMyController}}</div>

//in config
$routeProvider
  .when('/my/page/route/:id', { 
    templateUrl: 'myPage.html', 
  })

//in top level controller with $route injected
$scope.templateUrl = ''

$scope.$on('$routeChangeSuccess',function(){
  $scope.templateUrl = $route.current.templateUrl;
})

//in controller that doesn't reload
$scope.$on('$routeChangeSuccess',function(){
  //update your scope based on new $routeParams
})

কেবল নীচের দিকে হ'ল আপনি সমাধানের বৈশিষ্ট্যটি ব্যবহার করতে পারবেন না তবে এটি খুব সহজেই পাওয়া যায়। এছাড়াও আপনাকে নিয়ন্ত্রকের অবস্থা পরিচালনা করতে হবে, যেমন ara রুটপ্যারামের উপর ভিত্তি করে যুক্তি যেমন সংশ্লিষ্ট ইউআরএল পরিবর্তনের সাথে সাথে কন্ট্রোলারের মধ্যে রুট পরিবর্তিত হয়।

এখানে একটি উদাহরণ রয়েছে: http://plnkr.co/edit/WtAOm59CFcjafMmxBVOP?p= পূর্বরূপ


1
পিছনে বোতামটি plnkr এ সঠিকভাবে আচরণ করবে তা নিশ্চিত নয় ... আমি যেমন উল্লেখ করেছি যে, রুট পরিবর্তনের সাথে সাথে আপনাকে নিজেরাই কিছু জিনিস পরিচালনা করতে হবে .. এটি সর্বাধিক কোড-যোগ্য সমাধান নয়, তবে এটি কাজ করে
লুকাস

2

আমি এই সমাধানটি ব্যবহার করি

angular.module('reload-service.module', [])
.factory('reloadService', function($route,$timeout, $location) {
  return {
     preventReload: function($scope, navigateCallback) {
        var lastRoute = $route.current;

        $scope.$on('$locationChangeSuccess', function() {
           if (lastRoute.$$route.templateUrl === $route.current.$$route.templateUrl) {
              var routeParams = angular.copy($route.current.params);
              $route.current = lastRoute;
              navigateCallback(routeParams);
           }
        });
     }
  };
})

//usage
.controller('noReloadController', function($scope, $routeParams, reloadService) {
     $scope.routeParams = $routeParams;

     reloadService.preventReload($scope, function(newParams) {
        $scope.routeParams = newParams;
     });
});

এই পদ্ধতির পিছনে বোতামের কার্যকারিতা সংরক্ষণ করে এবং আমি সর্বদা বর্তমান রুটপ্যারামগুলি টেমপ্লেটে থাকি, অন্য কয়েকটি পদ্ধতির সাথে আমি দেখেছি unlike


1

গিটহাব এক সহ উপরের উত্তরগুলিতে আমার দৃশ্যের জন্য কিছু সমস্যা ছিল এবং ব্রাউজার থেকে ফিরে আসা বোতাম বা সরাসরি ইউআরএল পরিবর্তন নিয়ন্ত্রকটিকে পুনরায় লোড করছিল যা আমি পছন্দ করি না। আমি অবশেষে নিম্নলিখিত পদ্ধতির সাথে গিয়েছিলাম:

1. রুট সংজ্ঞাগুলিতে একটি সম্পত্তি নির্ধারণ করুন, আপনি যে রুটগুলি পরিবর্তনের সময় নিয়ন্ত্রণকারী পুনরায় লোড করতে চান না সেই রাস্তাগুলির জন্য 'NoReload' বলে '

.when('/:param1/:param2?/:param3?', {
    templateUrl: 'home.html',
    controller: 'HomeController',
    controllerAs: 'vm',
    noReload: true
})

২. আপনার মডিউলটির চলমান কার্যক্রমে, এই সমস্ত রুটগুলির জন্য যাচাই করা যুক্তি যুক্ত করুন। এটা তোলে রিলোড প্রতিরোধ করবে শুধুমাত্র যদি noReloadহয় trueএবং পূর্ববর্তী রুট নিয়ামক একই।

fooRun.$inject = ['$rootScope', '$route', '$routeParams'];

function fooRun($rootScope, $route, $routeParams) {
    $rootScope.$on('$routeChangeStart', function (event, nextRoute, lastRoute) {
        if (lastRoute && nextRoute.noReload 
         && lastRoute.controller === nextRoute.controller) {
            var un = $rootScope.$on('$locationChangeSuccess', function () {
                un();
                // Broadcast routeUpdate if params changed. Also update
                // $routeParams accordingly
                if (!angular.equals($route.current.params, lastRoute.params)) {
                    lastRoute.params = nextRoute.params;
                    angular.copy(lastRoute.params, $routeParams);
                    $rootScope.$broadcast('$routeUpdate', lastRoute);
                }
                // Prevent reload of controller by setting current
                // route to the previous one.
                $route.current = lastRoute;
            });
        }
    });
}

৩. অবশেষে, নিয়ামকটিতে, $ রুটআপডেট ইভেন্টটি শুনুন যাতে রুটের প্যারামিটারগুলি পরিবর্তিত হলে আপনি যা করতে হবে তা করতে পারেন।

HomeController.$inject = ['$scope', '$routeParams'];

function HomeController($scope, $routeParams) {
    //(...)

    $scope.$on("$routeUpdate", function handler(route) {
        // Do whatever you need to do with new $routeParams
        // You can also access the route from the parameter passed
        // to the event
    });

    //(...)
}

মনে রাখবেন যে এই পদ্ধতির সাহায্যে আপনি নিয়ামকের জিনিসগুলিকে পরিবর্তন করবেন না এবং তারপরে সেই অনুসারে পথ আপডেট করবেন। এটি অন্যভাবে। আপনি প্রথমে পথ পরিবর্তন করেন, তারপরে রুটের পরামিতিগুলি পরিবর্তিত হয়ে নিয়ন্ত্রকের মধ্যে জিনিসগুলি পরিবর্তন করতে $ রুটআপডেট ইভেন্টটি শুনুন।

এটি জিনিসগুলিকে সহজ এবং সামঞ্জস্যপূর্ণ রাখে কারণ আপনি যখন সরল পথ পরিবর্তন করেন (তবে আপনার পছন্দ মতো ব্যয়বহুল $ HTTP অনুরোধ ছাড়াই) এবং আপনি যখন ব্রাউজারটি পুরোপুরি পুনরায় লোড করেন তখন আপনি একই যুক্তি ব্যবহার করতে পারেন।


1

পুনরায় লোড না করে পথ পরিবর্তন করার সহজ উপায় রয়েছে

URL is - http://localhost:9000/#/edit_draft_inbox/1457

ইউআরএল পরিবর্তন করতে এই কোডটি ব্যবহার করুন, পৃষ্ঠা পুনর্নির্দেশ করা হবে না

দ্বিতীয় প্যারামিটার "মিথ্যা" খুব গুরুত্বপূর্ণ।

$location.path('/edit_draft_inbox/'+id, false);

এই AngularJS জন্য সঠিক নয় docs.angularjs.org/api/ng/service/$location
steampowered

0

আমার সম্পূর্ণ সমাধানটি যা কয়েকটি বিষয় সমাধান করে যা @ ভিগরন্ড এবং @ রহিলওয়াজির মিস করেছেন:

  • যখন অনুসন্ধানের প্যারামগুলি পরিবর্তন করা হয়েছিল, এটি একটি সম্প্রচারকে আটকাবে $routeUpdate
  • যখন রুটটি আসলে অপরিবর্তিত রেখে দেওয়া $locationChangeSuccessহয়, কখনই ট্রিগার করা হয় না যার ফলে পরবর্তী রুট আপডেট প্রতিরোধ করা হয়।
  • যদি একই ডাইজেস্ট চক্রটিতে অন্য একটি আপডেটের অনুরোধ থাকত, এবার পুনরায় লোড করার ইচ্ছা করে ইভেন্ট হ্যান্ডলার সেই পুনরায় লোডটি বাতিল করে দেবে।

    app.run(['$rootScope', '$route', '$location', '$timeout', function ($rootScope, $route, $location, $timeout) {
        ['url', 'path'].forEach(function (method) {
            var original = $location[method];
            var requestId = 0;
            $location[method] = function (param, reload) {
                // getter
                if (!param) return original.call($location);
    
                # only last call allowed to do things in one digest cycle
                var currentRequestId = ++requestId;
                if (reload === false) {
                    var lastRoute = $route.current;
                    // intercept ONLY the next $locateChangeSuccess
                    var un = $rootScope.$on('$locationChangeSuccess', function () {
                        un();
                        if (requestId !== currentRequestId) return;
    
                        if (!angular.equals($route.current.params, lastRoute.params)) {
                            // this should always be broadcast when params change
                            $rootScope.$broadcast('$routeUpdate');
                        }
                        var current = $route.current;
                        $route.current = lastRoute;
                        // make a route change to the previous route work
                        $timeout(function() {
                            if (requestId !== currentRequestId) return;
                            $route.current = current;
                        });
                    });
                    // if it didn't fire for some reason, don't intercept the next one
                    $timeout(un);
                }
                return original.call($location, param);
            };
        });
    }]);

টাইপোটি pathশেষে থাকতে হবে param, এছাড়াও এটি হ্যাশগুলির সাথে কাজ করে না, এবং আমার ঠিকানা বারের ইউআরএল আপডেট হয় না
ডেল্ট্রি

সংশোধন করা হয়েছে। এইচটিএমএল 5 ইউআরএল থাকা সত্ত্বেও হুম অদ্ভুত এটি আমার পক্ষে কাজ করে। এখনও আমার অনুমান করা কাউকে সাহায্য করতে পারে ...
ওদেড নিভ

0

হেড ট্যাগের ভিতরে নিম্নলিখিত যুক্ত করুন

  <script type="text/javascript">
    angular.element(document.getElementsByTagName('head')).append(angular.element('<base href="' + window.location.pathname + '" />'));
  </script>

এটি পুনরায় লোড প্রতিরোধ করবে।


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.