เราเตอร์ UI เชิงมุม: การเรียกใช้ฟังก์ชันของตัวควบคุมสถานะลูก

ฉันได้ทำงานกับ ui-router เชิงมุมและมีปัญหาหนึ่งยังคงเกิดขึ้น ฉันหวังว่าบางท่านสามารถให้คำแนะนำวิธีแก้ปัญหานี้ด้วยวิธีที่สะอาดและไม่แฮ็ก

พิจารณาสถานการณ์ต่อไปนี้:

ป้อนคำอธิบายรูปภาพที่นี่

ทางด้านซ้ายฉันมีการนำทางด้านข้างพร้อมรายชื่อผู้ติดต่อ เมื่อฉันคลิกที่ผู้ติดต่อ รายละเอียดของผู้ติดต่อที่เลือกจะแสดงในสถานะ app.contacts.details ทันทีที่ฉันเลือกผู้ติดต่อแล้ว การควบคุมบางอย่างจะปรากฏในส่วนหัว เช่น "แก้ไข" และ "ลบ" (ให้พิจารณาเป็นเพียงตัวอย่าง ในความเป็นจริงการกระทำเหล่านี้ซับซ้อนกว่า)

ตามหลักการแล้ว ปุ่มเหล่านี้จะเรียกใช้ฟังก์ชันของ detailStateController เช่น detailStateController.delete() เพื่อลบผู้ติดต่อที่เลือกในปัจจุบัน หรือ detailStateController.edit() เพื่อแก้ไขผู้ติดต่อที่เลือก (คุณเข้าใจแล้ว) แน่นอนว่าวิธีนี้ใช้ไม่ได้เนื่องจากปุ่มแก้ไขและลบไม่อยู่ในมุมมองของสถานะ app.contacts.details ดังนั้น detailStateController จึงไม่อยู่ในขอบเขต

ฉันรู้ว่าสิ่งนี้สามารถแก้ไขได้ด้วยการออกอากาศกิจกรรม แต่ฉันต้องการหลีกเลี่ยงการใช้กิจกรรมหากเป็นไปได้

คุณจะแก้ปัญหานี้อย่างไร?

คำแนะนำใด ๆ ที่ชื่นชมอย่างมาก


person omnibrain    schedule 31.05.2016    source แหล่งที่มา


คำตอบ (3)


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

app.factory("DataService", ["$http", function($http){
    var contacts = [];

    return {
        //sharing functions
        postItem: function(url, item) {
            return $http({
                url: url,
                method: 'POST',
                data: item
            });
        },
        putItem: function(url, item) {
            return $http({
                url: url,
                method: 'PUT',
                data: item
            });
        },
        deleteItem: function(url, item) {
            return $http({
                url: url,
                data: item,
                method: 'DELETE'
            });
        },
        setContacts = function(contacts) {
            contacts = contacts;
        },
        addContacts = function(contact) {
            contacts.push(contact);
        },
        deleteContact = function(contact) {
            var idx = this.contacts.indexOf(contact);
            contacts.splice(idx, 1);
        }
    };
}]);

จากนั้นในตัวควบคุมของคุณ:

app.controller("ContactDetailsCtrl", ["$scope", "DataService", function($scope, DataService){
    $scope.deleteContact = function() {
        DataService.deleteItem('path/to/delete', { contactId: 123 }).then(function(response) {
            //remove from client-side array once it's removed form db
            DataService.deleteContact(contact);
        }).catch(function(response){
            //an error occurred
        });
    }
}]);
person Kyle    schedule 31.05.2016

ฉันย้ายออกจากสไตล์นี้และเพียงจัดการทุกอย่างจากคอนโทรลเลอร์ด้วยรายการ หากคุณลบรายการออกจากตัวควบคุมรายละเอียดหรือแก้ไขฟิลด์ที่แสดงในตัวควบคุมหลัก คุณจะต้องอัปเดตตัวควบคุมรายการอยู่ดี ตอนที่ฉันทำแบบที่คุณทำอยู่ตอนนี้ ดูเหมือนว่าฉันต้องข้ามขั้นตอนพิเศษมากมายที่เกิดจากรายละเอียดในคอนโทรลเลอร์ตัวหนึ่งและรายการอยู่ในอีกตัวควบคุมหนึ่ง โดยทั่วไปฉันเพียงแค่มีคุณสมบัติรายการที่เป็นอาร์เรย์บนคอนโทรลเลอร์ของฉันและคุณสมบัติแถวปัจจุบันที่แสดงบันทึกทั้งหมด จากนั้นฉันใช้ ng-if เพื่อตรวจสอบแถวปัจจุบันและแสดงผลอย่างเหมาะสม เมื่อมีการคลิกแถว ฉันจะใช้ $location.search เพื่ออัปเดต URL และตรวจสอบการค้นหา $location เมื่อเริ่มต้นสำหรับการทำ Deep Link ซึ่งส่งผลให้มีคอนโทรลเลอร์ตัวเดียวที่มีขนาดใหญ่กว่าเล็กน้อย แต่ก็ยังเล็กกว่าคอนโทรลเลอร์ 2 ตัวรวมกัน หากฉันจัดการกับฟิลด์เพียงไม่กี่ฟิลด์ ฉันจะรวมฟิลด์ทั้งหมดไว้ในรายการด้วย หากมีข้อมูลจำนวนมาก ฉันจะโทรออกเมื่อรายการปัจจุบันในรายการมีการเปลี่ยนแปลงเพื่อรับข้อมูลสำหรับ currentRow และเพียงอัปเดต currentRow

person Mike Feltman    schedule 31.05.2016

โดยส่วนตัวแล้วฉันชอบสร้างโครงสร้างต่อไปนี้ในกรณีเช่นนี้

เราเตอร์ระบุว่า:

  • app.contacts.index - สำหรับบรรจุแถบเครื่องมือสำหรับรายละเอียด/มุมมองรายการ
  • app.contacts.list - สำหรับรายการ
  • app.contacts.detail - เพื่อดูรายละเอียด

ตัวควบคุม (สำหรับการตอบสนองแต่ละสถานะ):

function IndexCtrl($scope)
{
   $scope.contact = {}; // For containing the selected contact
   $scope.contacts = []; // List of contacts also on the parent view

   // Define Detail View functions here
   $scope.edit = Edit;
   $scope.delete = Delete;

   // Perform operations on $scope.contact/$scope.contacts
   function Edit() {}
   function Delete() {}
}

function DetailCtrl($scope)
{
    $scope.contact = $scope.$parent.contact = $scope.$parent.contacts[id]; // This way we work with the parent contact defined in IndexCtrl
}

function ListCtrl($scope, Contacts) 
{
    $scope.contacts = $scope.parent.contacts = Contacts.list(); // Contacts Service to retrieve the contact list
}
person Ankit Gupta    schedule 31.05.2016