Angularjs ขอบเขตการส่งผ่านระหว่างเส้นทาง


87

ฉันมีสถานการณ์ที่มีรูปแบบที่ขยายไปหลายหน้า (อาจไม่เหมาะ แต่เป็นอย่างนั้น) ฉันต้องการให้มีขอบเขตเดียวสำหรับแบบฟอร์มทั้งหมดที่ได้รับการกรอกข้อมูลในขณะที่คุณดำเนินการดังนั้นหากผู้ใช้ไปมาระหว่างขั้นตอนต่างๆคุณจะจำสถานะได้ง่าย

ดังนั้นฉันต้องทำในรหัสหลอกมาก:

  1. ชุด $scope.val = <Some dynamic data>
  2. คลิกลิงก์และกำหนดเส้นทางไปยังเทมเพลตใหม่ (อาจใช้คอนโทรลเลอร์เดียวกัน)
  3. $scope.val ควรจะยังคงเป็นค่าเดียวกับในหน้าสุดท้าย

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


เช่นเดียวกับส่วนเสริมของ ganaraj: ที่นี่คุณจะพบรายการบล็อกที่ดีจริงๆพร้อมกับ screencast เกี่ยวกับวิธีรับคอนโทรลเลอร์ที่แตกต่างกันในการสื่อสาร นอกจากนี้ยังมี jsfiddles ที่เป็นประโยชน์ให้เล่นด้วย onehungrymind.com/angularjs-communicating- ระหว่างตัวควบคุมฉันหวังว่ามันจะช่วยได้
F Lekschas

คำตอบ:


138

คุณต้องใช้บริการเนื่องจากบริการจะคงอยู่ตลอดอายุแอปของคุณ

สมมติว่าคุณต้องการบันทึกข้อมูลที่เกี่ยวข้องกับผู้ใช้

นี่คือวิธีที่คุณกำหนดบริการ:

app.factory("user",function(){
        return {};
});

ในคอนโทรลเลอร์แรกของคุณ:

app.controller( "RegistrationPage1Controller",function($scope,user){
    $scope.user = user;
    // and then set values on the object
    $scope.user.firstname = "John";
    $scope.user.secondname = "Smith";
});

app.controller( "RegistrationSecondPageController",function($scope,user){
        $scope.user = user;
        // and then set values on the object
        $scope.user.address = "1, Mars";

    });

6
อ๊ากก! ฉันลองมาก่อน แต่ไม่สามารถใช้งานได้เนื่องจากฉันใช้คอนโทรลเลอร์เดียวกันสำหรับทั้งสองเส้นทางดังนั้นในแต่ละเส้นทางใหม่ค่าเริ่มต้นจะเขียนทับค่าที่ฉันป้อนในหน้าก่อน ด้วยตัวควบคุมสองตัวหรือไม่มีค่าเริ่มต้นสิ่งนี้จะไม่เกิดขึ้นอีกต่อไป ขอบคุณ!
Erik Honn

1
อะไรคือสิ่งที่เกี่ยวกับValue Recipe docs.angularjs.org/guide/providersเช่นmyApp.value('clientId', 'a12345654321x');เป็นที่ถาวรระหว่างเส้นทางหรือไม่
Bndr

@TheBndr: มันควรจะเป็น ค่าเป็นเพียงรูปแบบบริการพิเศษตามที่ฉันเข้าใจ
Robert Koritnik

3
บริการจะไม่คงอยู่ข้อมูลหากคุณโหลดหน้านี้ซ้ำ ... ดังนั้นหากคุณอยู่ในหน้าที่ 4 ของแบบฟอร์มและโหลดหน้านั้นซ้ำคุณจะสูญเสียข้อมูลที่กรอกทั้งหมด
danielrvt

1
คำตอบที่ดี! เป็นจุดด้านคู่มือสไตล์สำหรับการผู้ที่อยู่ในคำตอบนี้ - บริการที่ไม่ได้เป็นตัวเองก่อสร้าง (ใช้คือเป็น XX ใหม่) ควรตั้งชื่อตัวพิมพ์เล็กอูฐ: github.com/mgechev/angularjs-style-guide
Matt Byrne

9

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

ฉันคิดว่าคุณกำลังใช้ui-routerดังนั้นคุณสามารถมีมุมมองที่มีชื่อซ้อนกัน จากนั้นในรหัสหลอก:

<div ng-controller="WizardController">
  <div name="stepView" ui-view/>
</div>

จากนั้น WizardController จะกำหนดตัวแปรขอบเขตที่คุณต้องการเก็บรักษาตามขั้นตอนของแบบฟอร์มหลายหน้า (ซึ่งฉันหมายถึง "ตัวช่วยสร้าง") จากนั้นเส้นทางของคุณจะอัปเดตstepViewเท่านั้น แต่ละขั้นตอนสามารถมีเทมเพลตตัวควบคุมและขอบเขตของตัวเองได้ แต่ขอบเขตจะหายไปจากหน้าไปอีกหน้าหนึ่ง แต่ขอบเขตใน WizardController จะถูกเก็บไว้ในทุกหน้า

ในการอัปเดตขอบเขต WizardController จากตัวควบคุมลูกคุณจะต้องใช้ไวยากรณ์เช่น$scope.$parent.myProp = 'value'หรือกำหนดฟังก์ชันsetMyPropบน WizardController สำหรับตัวแปรขอบเขตแต่ละตัว มิฉะนั้นหากคุณพยายามตั้งค่าตัวแปรขอบเขตหลักจากตัวควบคุมลูกโดยตรงคุณจะจบลงด้วยการสร้างตัวแปรขอบเขตใหม่บนตัวลูกเองโดยจะทำให้ตัวแปรหลักเป็นเงา

ยากที่จะอธิบายและขออภัยที่ไม่มีตัวอย่างเต็มรูปแบบ โดยทั่วไปคุณต้องการตัวควบคุมหลักที่สร้างขอบเขตหลักซึ่งจะถูกเก็บรักษาไว้ในทุกหน้าของแบบฟอร์มของคุณ


1
สิ่งนี้ใช้ได้กับ ui-router ใช่ (และเป็นวิธีที่ดีทีเดียวในการออกแบบหน้าเว็บแบบนั้น) แต่ไม่ใช่นอกกรอบ วิธีการบริการนอกกรอบคือวิธีที่จะไป
Erik Honn

1
เพื่อให้ชัดเจนคุณสมบัติขอบเขตหลักจะได้รับการสืบทอดโดยขอบเขตลูกเสมอ อย่างไรก็ตามหากคุณต้องการตั้งค่าคุณสมบัติขอบเขตหลักจากขอบเขตลูกคุณต้องเข้าถึงคุณสมบัตินั้นบนพาเรนต์มิฉะนั้นคุณกำลังสร้างคุณสมบัติใหม่ที่มีชื่อเดียวกันในขอบเขตลูก การตั้งค่าคุณสมบัติขอบเขตหลักสามารถทำได้โดยไปที่:$scope.$parent.myProp = 'hello world';
mbursill

1
นี่เป็นแนวทางที่ดีกว่าการใช้บริการ บริการเป็นแบบซิงเกิลดังนั้นสถานะใด ๆ ที่กำหนดไว้จะมีการใช้งานทั่วโลก หากผู้ใช้ออกจากตัวช่วยสร้างในบางส่วนจากนั้นเริ่มต้นใหม่อีกครั้งจะมีสถานะเหลืออยู่ในบริการจากการเรียกใช้ครั้งก่อนหน้า - เว้นแต่คุณจะแน่ใจว่าคุณทำความสะอาดบริการอย่างถูกต้องในทุกจุดออก แต่สามารถทำได้ กลายเป็นอาการปวดหัวในการบำรุงรักษาได้อย่างง่ายดาย!
Dan King

สนใจคำตอบนี้มากขึ้น
Kurai Bankusu

บริการเป็นสิ่งแรกที่ควรคำนึงถึงหากคุณไม่ได้ใช้ Angular UI Router หากคุณใช้ UI Router แต่มีการแก้ไขแบบซ้อนที่สามารถคงข้อมูลระหว่างมุมมองที่ซ้อนกันได้ ฉันคิดว่านั่นจะเป็นแนวทางที่สะอาดกว่าการพยายามเข้าถึงขอบเขตของผู้ปกครอง medium.com/opinionated-angularjs/…
losmescaleros

6

ข้อมูลสามารถส่งผ่านระหว่างคอนโทรลเลอร์ได้สองทาง

  1. $rootScope
  2. รุ่น

ตัวอย่างด้านล่างแสดงให้เห็นถึงการส่งผ่านค่าโดยใช้แบบจำลอง

app.js

angular.module('testApp')
  .controller('Controller', Controller)
  .controller('ControllerTwo', ControllerTwo)
  .factory('SharedService', SharedService);

SharedService.js

function SharedService($rootScope){

 return{
    objA: "value1",
    objB: "value2"
  }
}

// แก้ไขค่าในคอนโทรลเลอร์ก

Controller.js

function Controller($scope, SharedService){

 $scope.SharedService = SharedService;

 $scope.SharedService.objA = "value1 modified";
}

// เข้าถึงค่าใน controllertwo

ControllerTwo.js

function ControllerTwo($scope, SharedService){

 $scope.SharedService = SharedService;

 console.log("$scope.SharedService.objA"+$scope.SharedService.objA); // Prints "value1 modified"
}

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

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