为了学习 AngularFire,我正在尝试构建一个简单的 CRUD 应用程序。 INDEX 和 NEW 页面进展顺利,但我被困在 SHOW 和 EDIT 页面上。我无法在 SHOW 页面上显示选定的记录。
使用 MongoDB 和 Angular 可以轻松制作 SHOW 页面。在 INDEX 页面上,您放入一个锚链接,其中包含您要显示的记录的 ID:
<a ng-href="#/{{record._id}}"><span>{{record.title}}</span<</a>
这会将记录 ID 放入 URL,例如
www.website.com/#/K9hr32rhror
然后在 SHOW 页面上您可以使用
{{record.title}}
或 {{record.author}}
或任何您想要的。 Angular 会神奇地记住您在 INDEX 页面上单击的记录的 ID。我不知道 Angular 是如何做到这一点的。 :-)
在 MongoDB 中,ID 称为
_id
。在 Firebase 中,该 ID 称为 $id
。所以我将INDEX页面上的代码更改为
<a ng-href="#/{{record.$id}}"><span>{{record.title}}</span<</a>
这成功地将 ID 放入 URL 中。
问题是SHOW页面没有显示任何记录。 Angular 似乎忘记了
{{record}}
指的是什么。
我尝试输入领先
/
:
<a ng-href="/#/{{record._id}}"><span>{{record.title}}</span<</a>
这没有什么区别。
我尝试使用
从 URL 解析 IDvar key = location.hash.split('#/')[1]
这将返回 ID。当我 console.log $firebaseArray(ref) 对象时,我看到所有记录的集合(数组)。但是当我使用
collection.$getRecord(key)
或 collection.$keyAt(0)
或 collection.$indexFor(key)
时,我得到 null 或 -1,表明 AngularFire 找不到记录。
这是我的完整控制器代码:
app.controller('ShowController', ['$scope', '$firebaseArray', '$location',
function($scope, $firebaseArray, $location) {
var ref = new Firebase("https://my-firebase.firebaseio.com/");
list = $firebaseArray(ref);
console.log(list); // []
console.log(location.hash.split('#/')[1]); // -K9hr32rhror_
var key = location.hash.split('#/')[1];
console.log(list.$getRecord(key)); // null
console.log(list.$keyAt(0)); // null
console.log(list.$indexFor(key)); // -1
接下来我尝试使用
ng-repeat="record in collection | filter : key">
但我不知道 key
应该是什么。
我还用 google 搜索了“Angular Firebase CRUD SHOW 页面”,但示例 CRUD 应用程序都没有 SHOW 页面。我是否误解了一些基本的东西?例如,我应该在 INDEX 页面上使用
<ng-hide>
和 <ng-show>
构建 SHOW 和 EDIT 视图,而不费心制作单独的 SHOW 和 EDIT 页面吗?
您正在处理的问题是异步数据流。
app.controller('ShowController', ['$scope', '$firebaseArray', '$location',
function($scope, $firebaseArray, $location) {
var ref = new Firebase("https://my-firebase.firebaseio.com/");
var key = location.hash.split('#/')[1];
$scope.list = $firebaseArray(ref); // data is downloading
console.log($scope.list.length); // will be undefined, data is downloading
$scope.list.$loaded().then(function(list) {
console.log(list); // data has been downloaded!
list.$getRecord(key); // data is available
});
});
但是
.$loaded()
通常是不必要的,因为 AngularFire 知道何时触发 $digest
。在您的情况下,您想使用 $firebaseObject
。
app.controller('ShowController', ['$scope', '$firebaseObject', '$location',
function($scope, $firebaseObject, $location) {
var ref = new Firebase("https://my-firebase.firebaseio.com/");
var key = location.hash.split('#/')[1];
var itemRef = ref.child(key);
$scope.item = $firebaseObject(itemRef);
});
这会根据
key
抓取单个项目,而不是下载整个列表并取出一个项目。
谢谢 David East,问题是异步数据。这是两个工作控制器。第一个控制器获取数据数组并从数组中选择我想要的记录:
app.controller('ShowController', ['$scope', '$firebaseArray', '$location',
function($scope, $firebaseArray, $location) {
// set up Firebase
var ref = new Firebase("https://my-firebase.firebaseio.com/"); // goes to Firebase URL (fbURL)
var list = $firebaseArray(ref); // puts
list.$loaded().then(function(x) { // promise that executes when asynchronous data has loaded
var key = location.hash.split('#/')[1]; // parses key from URL query string
var showItem = list.$getRecord(key); // gets the record using the key passed in from the URL query string
var showItems = []; // make an array
showItems.push(showItem); // push the record into the array
$scope.showItems = showItems; // attach the array to $scope
// now 'ng-repeat="showIdea in showIdeas"' will iterate through the array, which has only one element
// i.e., this is how you make Angular display one thing
})
.catch(function(error) { // if the data doesn't load
console.log("Error:", error);
});
}]);
第二个控制器使用 David East 的建议,即使用
$firebaseObject
仅下载我想要的记录。我添加了一些代码以使其使用 ng-repeat
显示。还有另一种方法可以用 Angular 显示单个记录吗?
app.controller('ShowController', ['$scope', '$firebaseObject', '$location',
function($scope, $firebaseObject, $location) {
// set up Firebase
var ref = new Firebase("https://my-firebase.firebaseio.com/"); // goes to Firebase URL (fbURL)
var key = location.hash.split('#/')[1]; // parses key from URL query string
var itemRef = ref.child(key); // sets up the query
var showItems = []; // make an array
showItems.push($firebaseObject(itemRef)); // makes the query and push the record into the array
$scope.showItems = showItems; // attach the array to $scope
}]);
这是观点:
<table ng-repeat="showItem in showItems">
<tr><td>Name:</td><td>{{showItem.itemName}}</td></tr>
<tr><td>Title:</td><td>{{showItem.itemTitle}}</td></tr>
</table>
以简单的方式和形式进行 Angular firebase crud https://youtu.be/Ao4sdagqpvg
import { Injectable } from "@angular/core";
import { AngularFirestore } from "@angular/fire/firestore";
import User from "../models/user-model.model";
@Injectable({
providedIn: "root",
})
export class FireStoreService {
constructor(private _db: AngularFirestore) {
fireStore = this;
}
public async userDataById(uid: string) {
const userSnap = await this._db.doc(`users/${uid}`).get().toPromise();
return userSnap.data();
}
public async createUser(_id : string,userModel : User) {
try {
//Generate Firebase Id for New Node
//Push User Data in that Node
return this._db.collection('/User/').doc(_id).set({
isDelete: userModel.isDelete,
isActive: userModel.isActive
});
} catch(error) {
console.log(error)
return null;
}
}
public async getUsersListing() {
try {
// Query to get users where isDelete is false and isActive is true
const usersListingSnapshot = await this._db.firestore.collection("/User/")
.where("isDelete", "==", false)
.where("isActive", "==", true)
.get();
// Mapping the documents to data
const usersListings = usersListingSnapshot.docs.map((doc) => doc.data());
return usersListings;
} catch (error) {
console.error('Error getting user listings:', error);
return null;
}
}
public async getCaptionDetailsById(Id: string) {
try {
const querySnapshot = (await this._db.firestore.collection("/User/").get()).docs
.filter((doc) => doc.id === Id)
.map((doc) => doc.data());
return querySnapshot;
} catch (error) {
return null;
}
}
public async updateUserDetails(userModel: UserModel): Promise<boolean> {
try {
const result = await this._db.collection('/User/').doc(userModel.id).update({
name: userModel.name,
number: userModel.number,
gender: userModel.gender,
isVerify: userModel.isVerify,
updateAt: userModel.updateAt,
photo: userModel.photo,
});
return true;
} catch (error) {
console.error('Error updating user details:', error);
return false;
}
}
public async deleteData(id: string): Promise<Boolean> {
try {
// Mark the document as deleted instead of actually deleting it
await this._db.collection('/RouteMaster/').doc(id).update({ isDelete: true, isActive: false });
console.log(`Document with ID ${priceId} marked as deleted successfully`);
return true;
} catch (error) {
console.error('Error marking document as deleted:', error);
return false;
}
}
}