วิธีการใช้งานฟังก์ชั่นควบคุม AngularJS ในการโหลดหน้า


359

ขณะนี้ฉันมีหน้า Angular.js ที่อนุญาตให้ค้นหาและแสดงผลลัพธ์ ผู้ใช้คลิกที่ผลการค้นหาจากนั้นคลิกปุ่มย้อนกลับ ฉันต้องการให้แสดงผลการค้นหาอีกครั้ง แต่ฉันไม่สามารถหาวิธีที่จะทำให้การค้นหาดำเนินการได้ นี่คือรายละเอียด:

  • หน้า Angular.js ของฉันคือหน้าการค้นหาพร้อมช่องค้นหาและปุ่มค้นหา ผู้ใช้สามารถพิมพ์ด้วยตนเองในแบบสอบถามและกดปุ่มและแบบสอบถาม ajax ถูกยิงและผลลัพธ์จะปรากฏขึ้น ฉันอัปเดต URL ด้วยคำค้นหา ทำงานได้ดีทั้งหมด
  • ผู้ใช้คลิกที่ผลลัพธ์ของการค้นหาและนำไปยังหน้าอื่น - ซึ่งก็ใช้ได้เช่นกัน
  • ผู้ใช้คลิกปุ่มย้อนกลับและกลับไปที่หน้าการค้นหาเชิงมุมของฉันและ URL ที่ถูกต้องจะปรากฏขึ้นรวมถึงคำค้นหา ทำงานได้ดีทั้งหมด
  • ฉันผูกค่าฟิลด์การค้นหากับคำค้นหาใน URL ดังนั้นจึงมีคำค้นหาที่คาดหวัง ทำงานได้ดีทั้งหมด

ฉันจะให้ฟังก์ชันค้นหาดำเนินการอีกครั้งได้อย่างไรโดยที่ผู้ใช้ไม่ต้องกดปุ่ม "ค้นหา" ถ้ามันเป็น jquery ฉันจะใช้งานฟังก์ชั่นในฟังก์ชั่น documentready ฉันไม่เห็น Angular.js ที่เทียบเท่ากัน


คุณกำลังใช้$routepProvider? ใช้เพื่อเชื่อมต่อกับบริการในแอพของคุณที่ให้ข้อมูลสำหรับผลการค้นหา อย่าคิดในdocument.readyแง่เช่นเดียวกับ jQuery ยากที่จะช่วยได้มากโดยไม่ต้อง seing วิธีการที่คุณได้ค้นหาสายขึ้นในขณะนี้
charlietfl

คำตอบ:


430

ในอีกด้านหนึ่งตามที่ @ Mark-Rajcok กล่าวว่าคุณสามารถหนีไปกับฟังก์ชั่นส่วนตัวภายใน:

// at the bottom of your controller
var init = function () {
   // check if there is query in url
   // and fire search in case its value is not empty
};
// and fire it after definition
init();

นอกจากนี้คุณสามารถดูคำสั่งng-init การใช้งานจะเป็นเช่น:

// register controller in html
<div data-ng-controller="myCtrl" data-ng-init="init()"></div>

// in controller
$scope.init = function () {
    // check if there is query in url
    // and fire search in case its value is not empty
};

แต่ระวังเพราะเอกสารเชิงมุมหมายถึง (ตั้งแต่ v1.2) ที่จะไม่ใช้ng-initมัน อย่างไรก็ตาม imo มันขึ้นอยู่กับสถาปัตยกรรมของแอปของคุณ

ฉันใช้ng-initเมื่อฉันต้องการส่งค่าจากส่วนหลังไปยังแอพเชิงมุม:

<div data-ng-controller="myCtrl" data-ng-init="init('%some_backend_value%')"></div>

6
@Duke คุณไม่สามารถใส่เนื้อหาของฟังก์ชัน init () ที่ด้านล่างของคอนโทรลเลอร์ของคุณได้หรือไม่ คือทำไมคุณต้องใช้ ng-init และมีฟังก์ชั่น init () เมื่อผู้ใช้กดปุ่มย้อนกลับฉันถือว่าคุณกำลังเปลี่ยนมุมมองดังนั้นจึงมีmyCtrlการสร้างและควบคุมคอนโทรลเลอร์ใหม่ขึ้นมา
Mark Rajcok

24
ในขณะที่วิธีนี้ใช้งานได้ฉันลงคะแนนเพราะเอกสารประกอบคำแนะนำ ng-init ต่อสิ่งนี้ โดยเฉพาะ "การใช้ ngInit ที่เหมาะสมเพียงอย่างเดียวสำหรับนามแฝงคุณสมบัติพิเศษของ ngRepeat ดังที่เห็นในตัวอย่างด้านล่างนอกจากนี้คุณควรใช้ตัวควบคุมแทน ngInit เพื่อเริ่มต้นค่าในขอบเขต"
Jason Capriotti

1
คอนโทรลเลอร์ถูกสร้างอินสแตนซ์หลังจาก html อยู่ในตำแหน่ง
Dmitry Evseev

3
จะเกิดอะไรขึ้นถ้าคอนโทรลเลอร์ถูกนำมาใช้ซ้ำในหน้าอื่น แต่คุณต้องการเริ่มทำงานในหน้าใดหน้าหนึ่ง
Roberto Linares

3
@ RobertoLinares โดยส่วนตัวแล้วฉันพบว่าแนวทางเป็นสถานที่ที่ดีกว่าสำหรับการใช้งานซ้ำได้ คุณสามารถมีคำสั่งที่มีพารามิเตอร์ init <div smth on-init="doWhatever()">นี้: แน่นอนมันขึ้นอยู่กับกรณีการใช้งานบางอย่าง
Dmitry Evseev

135

ลองนี่สิ

$scope.$on('$viewContentLoaded', function() {
    //call it here
});

5
ขอบคุณสำหรับการตอบกลับ แต่คำตอบของ Dmitry ตรงกับสิ่งที่ฉันกำลังมองหา การวิจัยเพิ่มเติมดูเหมือนจะแนะนำกับ $ viewContentLoaded
Duke Dougal

7
กรณีการใช้งานแตกต่างกันเพียง ฉันใช้วิธีของมาร์คตลอดเวลาเช่นกัน
หลักการโฮโลแกรม

สำหรับกรณีการใช้งานของฉันนี่เป็นโซลูชั่นที่สมบูรณ์แบบ เราจำเป็นต้องเลือกข้อความโดยอัตโนมัติเพื่อกระตุ้นให้ผู้ใช้คัดลอก หน้าสามารถโหลดซ้ำ / มาหลายครั้งได้ดังนั้น $ viewContentLoaded จึงเป็นการจับคู่ที่ตรงกัน ขอบคุณ!
Olga Gnatenko

เป็นไปได้ไหมว่านี่จะถูกประหารชีวิตหลายครั้ง? ฉันได้รับพฤติกรรมที่ดูเหมือนว่าจะเป็นการล้อเลียนที่ ...
MadPhysicist

1
อันนี้ใช้ไม่ได้กับฉัน แต่เป็น $ scope $ watch ใช้งานได้ ความแตกต่างหลักคืออะไร?
Burak Tokak

59

ฉันไม่$viewContentLoadedสามารถทำงานให้ฉันได้และng-initควรใช้เฉพาะในng-repeat(ตามเอกสารประกอบ) และการเรียกใช้ฟังก์ชันในคอนโทรลเลอร์โดยตรงอาจทำให้เกิดข้อผิดพลาดได้หากรหัสนั้นอาศัยองค์ประกอบที่ยังไม่ได้กำหนด .

นี่คือสิ่งที่ฉันทำและได้ผลกับฉัน:

$scope.$on('$routeChangeSuccess', function () {
  // do something
});

ui-routerยกเว้นกรณีที่คุณกำลังใช้ จากนั้นก็คือ:

$scope.$on('$stateChangeSuccess', function () {
  // do something
});

1
คุณยอดเยี่ยมเพื่อนของฉัน
taco

สิ่งที่ฉันต้องการ ฉันกำลังมองหาสิ่งนี้อย่างแท้จริงเป็นเวลาสองวัน!
hellojebus

3
$scope.$on('$routeChangeSuccess'รุนแรงพารามิเตอร์ทุกครั้งที่มีการเปลี่ยนแปลงใน URL (ผ่าน$locationตัวอย่าง) $scope.$on('$locationChangeSuccess'และทำให้คุณสามารถใช้เพียง หากคุณต้องการทริกเกอร์ที่หน้าโหลด / โหลดใหม่คุณสามารถใช้$scope.$watch('$viewContentLoaded'ตามที่แนะนำที่นี่ มันจะไม่ทำงานระหว่างการเปลี่ยนพารามิเตอร์ URL
Neurotransmitter

ใช้ AngularJS 1.17.2 ตัวควบคุมภายใน$ routeChangeSuccessทำงานได้อย่างน่าอัศจรรย์ ... adam0101 ที่ยาวนาน ...
ArifMustafa

43
angular.element(document).ready(function () {

    // your code here

});

4
ต้องเป็นคำตอบที่ได้รับการยอมรับนี่เป็นวิธีที่ปลอดภัยกว่าที่จะทำ
Marwen Trabelsi

นี้เป็นสิ่งที่ดีถ้าเราไม่ได้ทำงานร่วมกับและแทนที่จะทำงานร่วมกับ$scope this
Akash

สิ่งนี้ต้องไปที่ไหน ฉันมีมันในแม่แบบของฉันและมันไม่ได้ถูกยิง
เดฟ

จะดีที่สุดในการฉีด $ document ในกรณีนี้หรือไม่ angular.element ($ document) .ready ...
jamie

4
คำอธิบายจะได้รับการชื่นชม
Hidayt Rahman

32

โซลูชันของ Dimitri / Mark ไม่ได้ผลสำหรับฉัน แต่การใช้ฟังก์ชัน$ timeoutดูเหมือนว่าจะทำงานได้ดีเพื่อให้แน่ใจว่ารหัสของคุณจะทำงานหลังจากมีการแสดงผลมาร์กอัปเท่านั้น

# Your controller, including $timeout

var $scope.init = function(){
 //your code
}

$timeout($scope.init)

หวังว่ามันจะช่วย


3
ในที่สุด นี่เป็นคนเดียวที่ทำงานให้ฉัน ขอบคุณ
zmirc

1
วิธีนี้ใช้ได้ผล นอกจากนี้อย่าลืมล้างการหมดเวลาด้วย $ timeout.cancel (ตัวจับเวลา) ที่คุณมี var timer = $ timeout ($ scope.init, มิลลิวินาที) เมื่อเริ่มต้นของคุณเสร็จแล้ว นอกจากนี้ฉันไม่คิดว่า $ scope ควรมี def 'var' ในรหัสของคุณด้านบน
Emmanuel NK

นี่ควรเป็นคำตอบที่ยอมรับได้ มันเป็นสิ่งเดียวที่ทำงานได้สำหรับฉัน (ลองคำตอบทั้งหมดข้างต้น) มันยังทำงานได้ถ้าคุณกำลังรอโหลด iframe
hello_fr1end

มันใช้งานได้! viewcontentLoaded ไม่ได้ผลสำหรับฉัน
Dark Knight

28

คุณสามารถทำได้หากคุณต้องการดูอ็อบเจ็กต์ DOM viewContentLoaded เพื่อเปลี่ยนจากนั้นทำอะไรบางอย่าง ใช้ $ scope $ on ใช้งานได้ แต่ต่างกันโดยเฉพาะเมื่อคุณมีโหมดหน้าเดียวในการกำหนดเส้นทางของคุณ

 $scope.$watch('$viewContentLoaded', function(){
    // do something
 });

7
โดยเฉพาะถ้าคุณใช้ $ rootScope $ watch แทนที่จะเป็น $ rootScope $ บนจะไม่ทำงานเมื่อมีการเปลี่ยนแปลงเส้นทางดังนั้นคุณสามารถใช้ตรรกะเฉพาะสำหรับการโหลดหน้าเริ่มต้น
csahlman



3

อีกทางเลือกหนึ่งหากคุณมีคอนโทรลเลอร์ที่เฉพาะเจาะจงกับหน้านั้น:

(function(){
    //code to run
}());

3

เมื่อใช้ $ routeProvider คุณสามารถแก้ไขใน. state และ bootstrap บริการของคุณ นี่คือการพูดว่าคุณกำลังจะโหลดตัวควบคุมและมุมมองหลังจากแก้ไขบริการของคุณ:

UI-เส้นทาง

 .state('nn', {
        url: "/nn",
        templateUrl: "views/home/n.html",
        controller: 'nnCtrl',
        resolve: {
          initialised: function (ourBootstrapService, $q) {

            var deferred = $q.defer();

            ourBootstrapService.init().then(function(initialised) {
              deferred.resolve(initialised);
            });
            return deferred.promise;
          }
        }
      })

บริการ

function ourBootstrapService() {

 function init(){ 
    // this is what we need
 }
}

3

พบคำตอบ Dmitry Evseev มีประโยชน์มาก

กรณีที่ 1: การใช้ angularJs เพียงอย่างเดียว:
เพื่อเรียกใช้เมธอดกับการโหลดหน้าเว็บคุณสามารถใช้ng-initในมุมมองและประกาศเมธอด init ในคอนโทรลเลอร์โดยกล่าวว่าไม่แนะนำให้ใช้ฟังก์ชั่นที่หนักกว่าตามเอกสาร DGL ใน ng-init :

คำสั่งนี้สามารถถูกใช้เพื่อเพิ่มจำนวนตรรกะที่ไม่จำเป็นในแม่แบบของคุณ มีการใช้งาน ngInit ที่เหมาะสมเพียงไม่กี่อย่างเช่นการลบล้างคุณสมบัติพิเศษของ ngRepeat ดังที่เห็นในตัวอย่างด้านล่าง และสำหรับการฉีดข้อมูลผ่านสคริปต์ฝั่งเซิร์ฟเวอร์ นอกเหนือจากกรณีเหล่านี้คุณควรใช้ตัวควบคุมแทน ngInit เพื่อเริ่มต้นค่าในขอบเขต

HTML:

<div ng-controller="searchController()">
    <!-- renaming view code here, including the search box and the buttons -->
</div>

ควบคุม:

app.controller('SearchCtrl', function(){

    var doSearch = function(keyword){
        //Search code here
    }

    doSearch($routeParams.searchKeyword);
})

คำเตือน:อย่าใช้ตัวควบคุมนี้สำหรับมุมมองอื่นที่มีเจตนาที่แตกต่างเพราะมันจะทำให้วิธีการค้นหาถูกเรียกใช้ที่นั่นเช่นกัน

กรณีที่ 2: การใช้ Ionic:
รหัสข้างต้นจะใช้งานได้เพียงตรวจสอบให้แน่ใจว่าแคชมุมมองถูกปิดใช้งานในรูปแบบroute.js:

route.js

.state('app', {
    url           : '/search',
    cache         : false, //disable caching of the view here
    templateUrl   : 'templates/search.html'   ,
    controller    : 'SearchCtrl'
  })

หวังว่านี่จะช่วยได้


1
นี่มีเพียงหนึ่งเดียวและอยู่ที่ด้านล่างสุดดีใจที่ฉันลงไปทั้งหมดcache: falseทำเพื่อฉัน - ขอบคุณ!
Rani Kheir

3

ฉันมีปัญหาเดียวกันและวิธีแก้ปัญหานี้ใช้งานได้สำหรับฉันเท่านั้น ฉันใช้สิ่งนี้เพื่อเลื่อนเพื่อยึดหลังจากโหลดหน้าแล้ว:

angular.element(window.document.body).ready(function () {

                        // Your function that runs after all DOM is loaded

                    });

2

คุณสามารถบันทึกผลลัพธ์การค้นหาในบริการทั่วไปซึ่งสามารถใช้ได้จากทุกที่และไม่ชัดเจนเมื่อนำทางไปยังหน้าอื่นแล้วคุณสามารถตั้งค่าผลลัพธ์การค้นหาด้วยข้อมูลที่บันทึกไว้สำหรับการคลิกปุ่มย้อนกลับ

function search(searchTerm) {
    // retrieve the data here;
    RetrievedData = CallService();
    CommonFunctionalityService.saveSerachResults(RetrievedData);
} 

สำหรับปุ่มย้อนกลับของคุณ

function Backbutton() {
    RetrievedData = CommonFunctionalityService.retrieveResults();
}

0

เรียกวิธีการเริ่มต้นภายในฟังก์ชั่นเริ่มต้นด้วยตนเอง

(function initController() {

    // do your initialize here

})();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.