简体   繁体   English

反应式表单,检查用户名是否存在

[英]Reactive Form , check if username exists

I have a problem in Ionic/Firebase with a value of validator in a reactive form.我在 Ionic/Firebase 中遇到了一个问题,验证器的值为反应形式。 In particular I have this 2 function below that check if a username in a realtime database of firebase exists.特别是我在下面有这 2 个 function,它检查 firebase 实时数据库中的用户名是否存在。 The 2 functions return a Promise boolean:这 2 个函数返回 Promise boolean:

export class UsernameValidator {
  static async getSnapshot(fc: FormControl){
    let isPresent:boolean = false;
    await firebase.database().ref().child("users").orderByChild("username")
    .equalTo(fc.value)
    .once("value", snapshot => {          
    }).then((data)=> {
      if(data.exists())
        isPresent = true;
      else
        isPresent = false;
    });
    console.log(isPresent);
    return isPresent; 
  }

  static async validUsername(fc: FormControl){
    try{
      let present:boolean =await UsernameValidator.getSnapshot(fc)
      if(present==true)
      return  (null);         
   else{
      return ({validUsername: true}); 
    } 
      }catch(e){
        console.log(e)
      }         
  }

Then, I have I class in which I define a FormGroup and validator:然后,我有我 class 我在其中定义了一个 FormGroup 和验证器:

constructor(private route: ActivatedRoute, private router: Router, 
              public pfService: ProfileService, public fb: FormBuilder,
              public authService: AuthenticationService) 
  {
    this.id = this.authService.userData.uid;
    //Underscore and dot can't be next to each other (e.g user_.name).
    //Underscore or dot can't be used multiple times in a row (e.g user__name / user..name).
    this.validPattern = "^(?=.{6,20}$)(?!.*[_.]{2})[a-z0-9._]+$"; 
    this.validPatternName = "^[a-z]{3,10}$";
    this.userForm = fb.group({
      txtUsername:  ["",[Validators.required,Validators.pattern(this.validPattern),
                                                  UsernameValidator.validUsername]],
      txtName:     ["",[Validators.required,Validators.pattern(this.validPatternName)]],
    });
    this.userForm .valueChanges.subscribe(()=> {
      console.log(this.userForm.getError('validUsername'))
      })
  };

The problem is that validUsername, from the console, is always null regardless of the value of isPresent, also when isPresent is false.问题是无论 isPresent 的值如何,控制台中的 validUsername 始终为 null,即使当 isPresent 为 false 时也是如此。 How can I fix this?我怎样才能解决这个问题?

You were close, but you've mixed different syntaxes in your attempts to fix the problem which has lead to confusion.您很接近,但是您在尝试解决导致混乱的问题时混合了不同的语法。

One other thing that is leading you into trouble, is confusing the two different types of DataSnapshot .导致您陷入麻烦的另一件事是混淆了两种不同类型的DataSnapshot

  • For a direct reference (eg database().ref("path/to/data") ), you can use exists() and val() to get information about that location's data.对于直接引用(例如database().ref("path/to/data") ),您可以使用exists()val()来获取有关该位置数据的信息。
  • For a queried reference (eg database().ref("path/to/group").orderByChild("name").equalTo("Tim's Group") ), the data is returned as a list where you can use numChildren() to get the number of matching results, hasChildren() to see if there are any results (similar to exists() ) and you can iterate through the results using forEach() .对于查询的引用(例如database().ref("path/to/group").orderByChild("name").equalTo("Tim's Group") ),数据以列表形式返回,您可以在其中使用numChildren()获取匹配结果的数量, hasChildren()查看是否有任何结果(类似于exists() ),您可以使用forEach()遍历结果。
static async isUsernameTaken(fc: FormControl) { // renamed from getSnapshot()
  return firebase.database().ref() // note the return here
    .child("users")
    .orderByChild("username")
    .equalTo(fc.value)
    .once("value")
    .then((querySnapshot) => querySnapshot.hasChildren());
}

However, I do not recommend searching /users for just usernames as it means that your user's data is world-readable and it's also inefficient.但是,我不建议在/users中仅搜索用户名,因为这意味着您的用户数据是全球可读的,而且效率也很低。 Instead you should create an index in your database that contains only usernames.相反,您应该在数据库中创建一个仅包含用户名的索引。

"/usernames": {
  "bob": "userId1",
  "frank": "userId2",
  "c00lguy": "userId3"
}

If you secure this using these Realtime Database Security Rules , you can also make use of the following simple functions.如果您使用这些实时数据库安全规则来保护这一点,您还可以使用以下简单功能。

{
  "usernames": {
    "$username": {
      // world readable
      ".read": true,

      // must be logged in to edit, you can only claim free usernames OR delete owned usernames
      ".write": "auth != null && (!newData.exists() || auth.uid == newData.val()) && (!data.exists() || data.val() == auth.uid)",

      // strings only
      ".validate": "newData.isString()",
    }
  }
}

To check if a username is available:要检查用户名是否可用:

static async isUsernameTaken(fc: FormControl) {
  return firebase.database().ref()
    .child("usernames")
    .child(fc.value)
    .once("value")
    .then((dataSnapshot) => dataSnapshot.exists());
}

To claim a username (if the write itself fails, assume the username is taken):声明用户名(如果写入失败,假设用户名被使用):

static async claimUsername(fc: FormControl) {
  const user = firebase.auth().currentUser;
  if (!user) {
    throw new Error("You need to login first!")
  }
 
  return firebase.database().ref()
    .child("usernames")
    .child(fc.value)
    .set(user.uid);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM