ฉันเริ่มทำงานกับ Angular Material
และมีปัญหาในการทำความเข้าใจปัญหาเกี่ยวกับฟังก์ชัน $scope
.apply
... ทุกครั้งที่ฉันพยายามแจ้ง UI เกี่ยวกับการเปลี่ยนแปลงโดยการเรียก apply
มันล้มเหลวโดยมีข้อผิดพลาด ฉันรู้ว่ามีคำถามที่คล้ายกันเกี่ยวกับ SO แต่ในกรณีของฉันข้อมูลไม่ได้ถูกจัดเก็บโดย scope
แต่โดยอินสแตนซ์ของตัวควบคุม...
ฉันยังใช้ TypeScript
สำหรับการใช้งานคอนโทรลเลอร์ของฉันด้วย ไม่แน่ใจ แต่ดูเหมือนว่าจะค่อนข้างแปลก เนื่องจากโค้ดตัวอย่างส่วนใหญ่ที่ฉันพบจะขึ้นอยู่กับการใช้งานคอนโทรลเลอร์แบบอินไลน์ในมุมมอง
คอนโทรลเลอร์ของฉันดูเหมือนว่า...
module MyApp {
export class MyController {
private scope: angular.IScope;
private http: angular.IHttpService;
public model: { data: SampleData } = { data: { } };
constructor($scope: angular.IScope, $http: angular.IHttpService) {
this.scope = $scope;
this.http = $http;
}
public querySampleData(): void {
const serviceEndpoint: string = "http://localhost:8080/api/";
var promise: ng.IHttpPromise<SampleData> = this.http.get(serviceEndpoint + "sample", { });
var callback: ng.IHttpPromiseCallback<SampleData> = (
data: SampleData,
status: number,
headers: angular.IHttpHeaderGetter,
config: angular.IRequestConfig) => {
this.scope.apply(() => {
this.model.data = data;
};
};
promise.success(callback);
}
}
export interface SampleData {
message? string;
}
}
คอนโทรลเลอร์จัดเตรียมเมธอด querySampleData
ซึ่งรับข้อมูลบางส่วนจากบริการระยะไกล (ใช้ IHttpService
สำหรับการเรียก API แบบอะซิงโครนัส) มุมมองจะใช้คอนโทรลเลอร์ในลักษณะดังต่อไปนี้...
<html ng-app="app">
<body ng-controller="MyController as c">
<div>
<button ng-click="c.querySampleData()"
aria-label="Query sample data">Query sample data</button>
<p>{{c.model.data.message}}</p>
</div>
...
<script src="../scripts/app.js"></script>
<script type="text/javascript">
var app = angular.module("app", ["ngMaterial"]);
app.controller("MyController", [ "$scope", "$http", MyApp.MyController ]);
</script>
</body>
</html>
การเริ่มต้นคอนโทรลเลอร์ทำงานได้ดี การขึ้นต่อกันทั้งหมดจะถูกฉีดเข้าไปในคอนโทรลเลอร์อย่างถูกต้อง และการโยงกับเมธอด querySampleData
ก็ทำงานได้ตามที่คาดไว้ (เมื่อฉันคลิกปุ่ม เมธอดจะถูกเรียก) หากฉันกำหนดข้อมูลที่ได้รับให้กับโมเดล UI จะไม่อัปเดต ดังนั้นฉันจึงเพิ่มการเรียกเมธอด $apply
เพื่อแจ้ง UI เกี่ยวกับการเปลี่ยนแปลง... ซึ่งทำให้ฉันมีข้อผิดพลาดดังที่กล่าวข้างต้น
อัปเดต:
เอกสารประกอบที่: https://docs.angularjs.org/error/$rootScope/inprog ขอแนะนำให้ใช้ $timeout
แทน $apply
เพื่อให้แน่ใจว่ามีการดำเนินการแบบอะซิงโครนัส แน่นอนว่านี่เป็นการแก้ไขข้อผิดพลาด แต่ UI ไม่เปลี่ยนแปลง...