Maison > interface Web > js tutoriel > le corps du texte

Parlons de la façon de créer des applications angulaires à l'aide de MemFire ​​​​Cloud

青灯夜游
Libérer: 2022-08-30 20:44:12
avant
1718 Les gens l'ont consulté

Comment créer une application Angular ? L'article suivant vous présentera comment utiliser MemFire ​​​​Cloud pour créer des applications angulaires. J'espère qu'il vous sera utile !

Parlons de la façon de créer des applications angulaires à l'aide de MemFire ​​​​Cloud

【Recommandation de didacticiel connexe : "Tutoriel angulaire"】

MemFire ​​​​Cloud est une base de données cloud qui offre aux utilisateurs la possibilité de créer des bases de données cloud, de gérer la base de données et de sauvegarder la base de données. Il fournit également un backend en tant que service. Les utilisateurs peuvent créer une nouvelle application en 1 minute, utiliser des API et des SDK générés automatiquement et accéder aux bases de données cloud, au stockage d'objets, à l'authentification et à l'autorisation des utilisateurs, ainsi qu'à d'autres fonctions. coder et accélérer le développement d’applications WEB ou APP.

Adresse de la vidéo d'apprentissage : www.bilibili.com/video/BV1wt…

Cet exemple fournit les étapes pour créer une application de gestion d'utilisateurs simple (à partir de zéro) en utilisant MemFire ​​​​Cloud et angulaire. Cela inclut :

  • MemFire ​​​​Cloud : base de données MemFireDB pour stocker les données utilisateur.
  • Vérification de l'utilisateur MemFire ​​​​Cloud : les utilisateurs peuvent se connecter en utilisant le lien magique (uniquement l'e-mail requis, aucun mot de passe requis).
  • MemFire ​​​​Cloud Storage : les utilisateurs peuvent télécharger des photos.
  • Politique de sécurité au niveau de la ligne : les données sont protégées afin que les individus ne puissent accéder qu'à leurs propres données.
  • API instantanée : l'API est automatiquement générée lors de la création d'une table de base de données.

À la fin de ce guide, vous disposerez d'une application qui permet aux utilisateurs de se connecter et de mettre à jour certains détails de base de leur profil :

Parlons de la façon de créer des applications angulaires à laide de MemFire ​​​​Cloud

Création de l'application

Objectif : Notre application est créée ici Obtenir une série de ressources tels que les bases de données et le stockage cloud, et obtenez le lien d'accès API exclusif et la clé d'accès de l'application. Les utilisateurs peuvent facilement interagir avec les ressources ci-dessus.

Connexioncloud.memfiredb.com/auth/loginCréer une application

Parlons de la façon de créer des applications angulaires à laide de MemFire ​​​​Cloud

Créer une table de données

Cliquez sur l'application pour créer visuellement la table de données

1 Créer la table des profils ;

Sur les données. page de la table, cliquez sur "Nouvelle table de données", la configuration de la page est la suivante :

Parlons de la façon de créer des applications angulaires à laide de MemFire ​​​​Cloud

où l'identifiant du champ de la table des profils est lié à la clé étrangère du champ id (type uuid) dans la table auth.users.

2. Activez les règles d'accès de sécurité aux données RLS pour les profils ;

Sélectionnez la table Profils créée, cliquez sur la barre d'autorisation de la table, comme indiqué dans la figure ci-dessous, cliquez sur le bouton "Activer RLS"

Parlons de la façon de créer des applications angulaires à laide de MemFire ​​​​Cloud

3. chaque utilisateur pour afficher les informations personnelles publiques ;

Cliquez sur le bouton « Nouvelle règle », dans la boîte de dialogue contextuelle, sélectionnez « Activer l'accès pour tous les utilisateurs », saisissez le nom de la politique, sélectionnez l'opération « SÉLECTIONNER (requête) » et cliquez sur le bouton « Créer une politique », comme indiqué ci-dessous.

Parlons de la façon de créer des applications angulaires à laide de MemFire ​​​​Cloud

4. Autorisez uniquement les utilisateurs à ajouter, supprimer, modifier et vérifier leurs informations de profil personnel ;

Cliquez sur le bouton "Nouvelle règle", dans la boîte contextuelle, sélectionnez "Activer les autorisations d'accès pour les utilisateurs en fonction de l'utilisateur". ID" et entrez le nom de la stratégie. Sélectionnez l'opération "TOUS" et cliquez sur le bouton "Créer une stratégie", comme indiqué ci-dessous.

Parlons de la façon de créer des applications angulaires à laide de MemFire ​​​​Cloud

Créer un bucket d'avatars

Créez un bucket de stockage cloud pour stocker l'image de l'avatar de l'utilisateur. Les opérations impliquées incluent :

1. Créez un bucket d'avatars

Accédez au stockage cloud de la colonne de l'application, cliquez sur. le bouton "Nouveau bucket" pour créer des avatars de bucket.

Parlons de la façon de créer des applications angulaires à laide de MemFire ​​​​Cloud

2. Autorisez chaque utilisateur à afficher les avatars du bucket

Sélectionnez les avatars du bucket, passez à la colonne Paramètres d'autorisation, cliquez sur le bouton "Nouvelle règle", une boîte de dialogue contextuelle d'édition de politique apparaîtra, sélectionnez "Personnalisé", comme le montre l'image ci-dessous :

Parlons de la façon de créer des applications angulaires à laide de MemFire ​​​​Cloud

Sélectionnez l'opération SELECT, entrez le nom de la stratégie et cliquez sur le bouton « Générer une stratégie », comme indiqué dans la figure ci-dessous.

Parlons de la façon de créer des applications angulaires à laide de MemFire ​​​​Cloud

3. Autorisez les utilisateurs à télécharger des avatars de bucket ;

Sélectionnez les avatars de bucket, passez à la colonne Paramètres d'autorisation, cliquez sur le bouton "Nouvelle règle", une boîte de dialogue d'édition de politique apparaîtra, sélectionnez "Personnalisé", comme indiqué ci-dessous Comme indiqué :

Parlons de la façon de créer des applications angulaires à laide de MemFire ​​​​Cloud

Sélectionnez l'opération INSÉRER, entrez le nom de la stratégie et cliquez sur le bouton "Générer une stratégie", comme indiqué dans la figure ci-dessous.

1Parlons de la façon de créer des applications angulaires à laide de MemFire ​​​​Cloud

Afficher les résultats

1Parlons de la façon de créer des applications angulaires à laide de MemFire ​​​​Cloud

Toutes les tables de données et SQL de RLS (le nom de la stratégie est remplacé par l'anglais)

-- Create a table for public "profiles"
create table profiles (
  id uuid references auth.users not null,
  updated_at timestamp with time zone,
  username text unique,
  avatar_url text,
  website text,

  primary key (id),
  unique(username),
);

alter table profiles enable row level security;

create policy "Public profiles are viewable by everyone."
  on profiles for select
  using ( true );

create policy "Users can insert their own profile."
  on profiles for insert
  with check ( auth.uid() = id );

create policy "Users can update own profile."
  on profiles for update
  using ( auth.uid() = id );
-- Set up Storage!
insert into storage.buckets (id, name)
values ('avatars', 'avatars');

create policy "Avatar images are publicly accessible."
  on storage.objects for select
  using ( bucket_id = 'avatars' );

create policy "Anyone can upload an avatar."
  on storage.objects for insert
  with check ( bucket_id = 'avatars' );
Copier après la connexion

Obtenir la clé API

Maintenant que vous avez créé des tables de base de données, vous pouvez utiliser la API générée pour insérer des données. Nous avons juste besoin d'obtenir l'URL et la clé d'anon à partir des paramètres de l'API.

Sur la page Application->Résumé, obtenez l'adresse du service et les informations sur le jeton.

La clé Anon (publique) est la clé API du client. Il permet un « accès anonyme » à votre base de données jusqu'à ce que l'utilisateur se connecte. Après la connexion, la clé est remplacée par le propre jeton de connexion de l'utilisateur. Cela permettra la sécurité au niveau des lignes pour les données.

REMARQUE : La clé service_role (secret) permet un accès complet à vos données, en contournant toute politique de sécurité. Cette clé doit être gardée secrète et utilisée dans un environnement serveur, jamais sur le client ou le navigateur. Dans l’exemple de code suivant, supabaseUrl et supabaseKey doivent être fournis.

Paramètres d'authentification

Lorsque l'utilisateur clique sur le lien magique dans l'e-mail pour se connecter, il doit accéder à l'interface de connexion de notre application. Ici, vous devez configurer la redirection d'URL appropriée dans les paramètres d'authentification.

Parce que notre application finale sera démarrée sur le port local 4200 (ou d'autres ports), nous définissons donc ici temporairement l'url sur http://localhost:4200

De plus, cette interface peut également être personnalisée. Utilisez notre propre smtp serveur.

Créer l'application

Créons une application Angular à partir de zéro.

Initialiser le projet

Nous pouvons utiliser Angular CLI pour initialiser un projet nommé memfiredb-angular : memfiredb-angular

Angular 需要 Node.js (>=14.15

npm install -g @angular/cli
npx ng new memfiredb-angular --routing false --style css
cd memfiredb-angular
Copier après la connexion

然后让我们安装唯一的附加依赖项:supabase-js

npm install @supabase/supabase-js
Copier après la connexion

最后,我们要将环境变量保存在environment.ts, 我们需要的是 API URL 和您上面anon复制的密钥。

src/environments/environment.ts文件

export const environment = {
  production: false,
  supabaseUrl: "YOUR_SUPABASE_URL",
  supabaseKey: "YOUR_SUPABASE_KEY"
};
Copier après la connexion

现在我们已经有了 API 凭证,通过ng g s supabase创建一个SupabaseService来初始化 Supabase 客户端并实现与 Supabase API 通信的函数。

src/app/supabase.service.ts

import { Injectable } from '@angular/core';
import {AuthChangeEvent, createClient, Session, SupabaseClient} from '@supabase/supabase-js';
import {environment} from "../environments/environment";

export interface Profile {
  username: string;
  website: string;
  avatar_url: string;
}

@Injectable({
  providedIn: 'root'
})
export class SupabaseService {
  private supabase: SupabaseClient;

  constructor() {
    this.supabase = createClient(environment.supabaseUrl, environment.supabaseKey);
  }

  get user() {
    return this.supabase.auth.user();
  }

  get session() {
    return this.supabase.auth.session();
  }

  get profile() {
    return this.supabase
      .from('profiles')
      .select(`username, website, avatar_url`)
      .eq('id', this.user?.id)
      .single();
  }

  authChanges(callback: (event: AuthChangeEvent, session: Session | null) => void) {
    return this.supabase.auth.onAuthStateChange(callback);
  }

  signIn(email: string) {
    return this.supabase.auth.signIn({email});
  }

  signOut() {
    return this.supabase.auth.signOut();
  }

  updateProfile(profile: Profile) {
    const update = {
      ...profile,
      id: this.user?.id,
      updated_at: new Date()
    }

    return this.supabase.from('profiles').upsert(update, {
      returning: 'minimal', // Don't return the value after inserting
    });
  }

  downLoadImage(path: string) {
    return this.supabase.storage.from('avatars').download(path);
  }

  uploadAvatar(filePath: string, file: File) {
    return this.supabase.storage
      .from('avatars')
      .upload(filePath, file);
  }
}
Copier après la connexion

更新样式

可以看到界面实在是不怎么优雅,更新下样式,让它好看一些。 修改src/styles.css文件。

html,
body {
  --custom-font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu,
    Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  --custom-bg-color: #101010;
  --custom-panel-color: #222;
  --custom-box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.8);
  --custom-color: #fff;
  --custom-color-brand: #24b47e;
  --custom-color-secondary: #666;
  --custom-border: 1px solid #333;
  --custom-border-radius: 5px;
  --custom-spacing: 5px;

  padding: 0;
  margin: 0;
  font-family: var(--custom-font-family);
  background-color: var(--custom-bg-color);
}

* {
  color: var(--custom-color);
  font-family: var(--custom-font-family);
  box-sizing: border-box;
}

html,
body,
#__next {
  height: 100vh;
  width: 100vw;
  overflow-x: hidden;
}

/* Grid */

.container {
  width: 90%;
  margin-left: auto;
  margin-right: auto;
}
.row {
  position: relative;
  width: 100%;
}
.row [class^='col'] {
  float: left;
  margin: 0.5rem 2%;
  min-height: 0.125rem;
}
.col-1,
.col-2,
.col-3,
.col-4,
.col-5,
.col-6,
.col-7,
.col-8,
.col-9,
.col-10,
.col-11,
.col-12 {
  width: 96%;
}
.col-1-sm {
  width: 4.33%;
}
.col-2-sm {
  width: 12.66%;
}
.col-3-sm {
  width: 21%;
}
.col-4-sm {
  width: 29.33%;
}
.col-5-sm {
  width: 37.66%;
}
.col-6-sm {
  width: 46%;
}
.col-7-sm {
  width: 54.33%;
}
.col-8-sm {
  width: 62.66%;
}
.col-9-sm {
  width: 71%;
}
.col-10-sm {
  width: 79.33%;
}
.col-11-sm {
  width: 87.66%;
}
.col-12-sm {
  width: 96%;
}
.row::after {
  content: '';
  display: table;
  clear: both;
}
.hidden-sm {
  display: none;
}

@media only screen and (min-width: 33.75em) {
  /* 540px */
  .container {
    width: 80%;
  }
}

@media only screen and (min-width: 45em) {
  /* 720px */
  .col-1 {
    width: 4.33%;
  }
  .col-2 {
    width: 12.66%;
  }
  .col-3 {
    width: 21%;
  }
  .col-4 {
    width: 29.33%;
  }
  .col-5 {
    width: 37.66%;
  }
  .col-6 {
    width: 46%;
  }
  .col-7 {
    width: 54.33%;
  }
  .col-8 {
    width: 62.66%;
  }
  .col-9 {
    width: 71%;
  }
  .col-10 {
    width: 79.33%;
  }
  .col-11 {
    width: 87.66%;
  }
  .col-12 {
    width: 96%;
  }
  .hidden-sm {
    display: block;
  }
}

@media only screen and (min-width: 60em) {
  /* 960px */
  .container {
    width: 75%;
    max-width: 60rem;
  }
}

/* Forms */

label {
  display: block;
  margin: 5px 0;
  color: var(--custom-color-secondary);
  font-size: 0.8rem;
  text-transform: uppercase;
}

input {
  width: 100%;
  border-radius: 5px;
  border: var(--custom-border);
  padding: 8px;
  font-size: 0.9rem;
  background-color: var(--custom-bg-color);
  color: var(--custom-color);
}

input[disabled] {
  color: var(--custom-color-secondary);
}

/* Utils */

.block {
  display: block;
  width: 100%;
}
.inline-block {
  display: inline-block;
  width: 100%;
}
.flex {
  display: flex;
}
.flex.column {
  flex-direction: column;
}
.flex.row {
  flex-direction: row;
}
.flex.flex-1 {
  flex: 1 1 0;
}
.flex-end {
  justify-content: flex-end;
}
.flex-center {
  justify-content: center;
}
.items-center {
  align-items: center;
}
.text-sm {
  font-size: 0.8rem;
  font-weight: 300;
}
.text-right {
  text-align: right;
}
.font-light {
  font-weight: 300;
}
.opacity-half {
  opacity: 50%;
}

/* Button */

button,
.button {
  color: var(--custom-color);
  border: var(--custom-border);
  background-color: var(--custom-bg-color);
  display: inline-block;
  text-align: center;
  border-radius: var(--custom-border-radius);
  padding: 0.5rem 1rem;
  cursor: pointer;
  text-align: center;
  font-size: 0.9rem;
  text-transform: uppercase;
}

button.primary,
.button.primary {
  background-color: var(--custom-color-brand);
  border: 1px solid var(--custom-color-brand);
}

/* Widgets */

.card {
  width: 100%;
  display: block;
  border: var(--custom-border);
  border-radius: var(--custom-border-radius);
  padding: var(--custom-spacing);
}

.avatar {
  border-radius: var(--custom-border-radius);
  overflow: hidden;
  max-width: 100%;
}
.avatar.image {
  object-fit: cover;
}
.avatar.no-image {
  background-color: #333;
  border: 1px solid rgb(200, 200, 200);
  border-radius: 5px;
}

.footer {
  position: absolute;
  max-width: 100%;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  flex-flow: row;
  border-top: var(--custom-border);
  background-color: var(--custom-bg-color);
}
.footer div {
  padding: var(--custom-spacing);
  display: flex;
  align-items: center;
  width: 100%;
}
.footer div > img {
  height: 20px;
  margin-left: 10px;
}
.footer > div:first-child {
  display: none;
}
.footer > div:nth-child(2) {
  justify-content: left;
}

@media only screen and (min-width: 60em) {
  /* 960px */
  .footer > div:first-child {
    display: flex;
  }
  .footer > div:nth-child(2) {
    justify-content: center;
  }
}

@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.mainHeader {
  width: 100%;
  font-size: 1.3rem;
  margin-bottom: 20px;
}

.avatarPlaceholder {
  border: var(--custom-border);
  border-radius: var(--custom-border-radius);
  width: 35px;
  height: 35px;
  background-color: rgba(255, 255, 255, 0.2);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Auth */

.auth-widget {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.auth-widget > .button {
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background-color: #444444;
  text-transform: none !important;
  transition: all 0.2s ease;
}

.auth-widget .button:hover {
  background-color: #2a2a2a;
}

.auth-widget .button > .loader {
  width: 17px;
  animation: spin 1s linear infinite;
  filter: invert(1);
}

/* Account */

.account {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.account > * > .avatarField {
  display: flex;
  align-items: center;
  margin-bottom: 30px;
}

.account > * > .avatarField > .avatarContainer {
  margin-right: 20px;
}

/* Profile Card */

.profileCard {
  border-radius: 5px;
  display: flex;
  border: var(--custom-border);
  background-color: var(--custom-panel-color);
  padding: 20px 20px;
  margin-bottom: 20px;
}

.profileCard:last-child {
  margin-bottom: 0px;
}

.profileCard > .userInfo {
  margin-left: 20px;
  font-weight: 300;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.profileCard > .userInfo > p {
  margin: 0;
}

.profileCard > .userInfo > .username {
  font-size: 1.3rem;
  font-weight: 500;
  margin-bottom: 5px;
}

.profileCard > .userInfo > .website {
  font-size: 0.9rem;
  color: var(--custom-color-brand);
  margin-bottom: 10px;
  text-decoration: none;
}
Copier après la connexion

设置登录组件

让我们设置一个 Angular 组件来管理登录和注册。我们将使用 Magic Links,因此用户无需使用密码即可使用电子邮件登录。使用Angular CLI 命令创建一个AuthComponent 。 ng g c auth

src/app/auth/auth.component.ts

import { Component } from '@angular/core';
import {SupabaseService} from "../supabase.service";

@Component({
  selector: 'app-auth',
  template: `
    <div>
      <form>
        <h1>Memfiredb + Angular</h1>
        <p>使用下面的电子邮件通过魔术链接登录</p>
        <div>
          <input>
        </div>
        <div>
          <button>
          {{loading ? 'Loading' : 'Send magic link'}}
          </button>
        </div>
      </form>
    </div>
  `,
})
export class AuthComponent {
  loading = false;

  constructor(private readonly supabase: SupabaseService) { }

  async handleLogin(input: string) {
    try {
      this.loading = true;
      await this.supabase.signIn(input);
      alert('请检查您的电子邮件以获取登录链接!');
    } catch (error:any) {
      alert(error.error_description || error.message)
    } finally {
      this.loading = false;
    }
  }
}
Copier après la connexion

用户信息页面

用户登录后,我们可以允许他们编辑他们的个人资料详细信息并管理他们的帐户。使用Angular CLI 命令创建一个AccountComponent 。 ng g c account

Angular nécessite Node.js (>=14.15
import {Component, Input, OnInit} from '@angular/core';
import {Profile, SupabaseService} from "../supabase.service";
import {Session} from "@supabase/supabase-js";

@Component({
  selector: 'app-account',
  template: `
    <div>
      <div>
        <label>邮箱</label>
        <input>
      </div>
      <div>
        <label>名称</label>
        <input>
      </div>
      <div>
        <label>网址</label>
        <input>
      </div>

      <div>
        <button>
          {{loading ? 'Loading ...' : 'Update'}}
        </button>
      </div>

      <div>
        <button>
          退出登录
        </button>
      </div>
    </div>
  `
})
export class AccountComponent implements OnInit {
  loading = false;
  profile: Profile | undefined;

  @Input() session: Session | undefined;

  constructor(private readonly supabase: SupabaseService) { }

  ngOnInit() {
    this.getProfile();
  }

  async getProfile() {
    try {
      this.loading = true;
      let {data: profile, error, status} = await this.supabase.profile;

      if (error && status !== 406) {
        throw error;
      }

      if (profile) {
        this.profile = profile;
      }
    } catch (error:any) {
      alert(error.message)
    } finally {
      this.loading = false;
    }
  }

  async updateProfile(username: string, website: string, avatar_url: string = '') {
    try {
      this.loading = true;
      await this.supabase.updateProfile({username, website, avatar_url});
    } catch (error:any) {
      alert(error.message);
    } finally {
      this.loading = false;
    }
  }

  async signOut() {
    await this.supabase.signOut();
  }
}
Copier après la connexion
Ensuite, installons la seule dépendance supplémentaire : supabase-js

import {Component, OnInit} from '@angular/core';
import {SupabaseService} from "./supabase.service";

@Component({
  selector: 'app-root',
  template: `
  <div>
    <app-account></app-account>
    <ng-template>
      <app-auth></app-auth>
    </ng-template>
  </div>
  `
})
export class AppComponent implements OnInit {
  session = this.supabase.session;

  constructor(private readonly supabase: SupabaseService) { }

  ngOnInit() {
    this.supabase.authChanges((_, session) => this.session = session);
  }
}
Copier après la connexion
Copier après la connexion
Enfin, nous devons enregistrer les variables d'environnement dans Environment.ts. Ce dont nous avons besoin, c'est de l'URL de l'API et de la clé que vous avez copiée ci-dessus anon.

fichier src/environments/environment.ts

npm run start
Copier après la connexion
Copier après la connexion
Maintenant que nous avons les informations d'identification de l'API, créez un

SupabaseService🎜 via ng g s supabase pour initialiser le client Supabase et implémenter des fonctions pour communiquer avec la Supabase API. 🎜🎜src/app/supabase.service.ts🎜
import {Component, EventEmitter, Input, Output} from '@angular/core';
import {SupabaseService} from "../supabase.service";
import {DomSanitizer, SafeResourceUrl} from "@angular/platform-browser";

@Component({
  selector: 'app-avatar',
  template: `
    <div>
      <img  alt="Parlons de la façon de créer des applications angulaires à l'aide de MemFire ​​​​Cloud" >
</div>
    <div></div>
    <div>
      <label>
        {{uploading ? 'Uploading ...' : 'Upload'}}
      </label>
      <input>
    </div>
  `,
})
export class AvatarComponent {
  _avatarUrl: SafeResourceUrl | undefined;
  uploading = false;

  @Input()
  set avatarUrl(url: string | undefined) {
    if (url) {
      this.downloadImage(url);
    }
  };

  @Output() upload = new EventEmitter<string>();

  constructor(
    private readonly supabase: SupabaseService,
    private readonly dom: DomSanitizer
  ) { }

  async downloadImage(path: string) {
    try {
      const {data} = await this.supabase.downLoadImage(path);
       if (data instanceof Blob) {
        this._avatarUrl = this.dom.bypassSecurityTrustResourceUrl(
          URL.createObjectURL(data)
        );
      }
    } catch (error:any) {
      console.error('下载图片出错: ', error.message);
    }
  }

  async uploadAvatar(event: any) {
    try {
      this.uploading = true;
      if (!event.target.files || event.target.files.length === 0) {
        throw new Error('必须选择要上载的图像。');
      }

      const file = event.target.files[0];
      const fileExt = file.name.split('.').pop();
      const fileName = `${Math.random()}.${fileExt}`;
      const filePath = `${fileName}`;

      await this.supabase.uploadAvatar(filePath, file);
      this.upload.emit(filePath);
      this.downloadImage(filePath)
    } catch (error:any) {
      alert(error.message);
    } finally {
      this.uploading = false;
    }
  }
}</string>
Copier après la connexion
Copier après la connexion

🎜Mettre à jour le style🎜🎜🎜Vous voyez que l'interface n'est vraiment pas très élégante, mettez à jour le style pour lui donner un aspect mieux. Modifiez le fichier src/styles.css. 🎜
import {Component, Input, OnInit} from '@angular/core';
import {Profile, SupabaseService} from "../supabase.service";
import {Session} from "@supabase/supabase-js";

@Component({
  selector: 'app-account',
  template: `
      <app-avatar>
    </app-avatar>
    <div>
      <div>
        <label>邮箱</label>
        <input>
      </div>
      <div>
        <label>名称</label>
        <input>
      </div>
      <div>
        <label>网址</label>
        <input>
      </div>

      <div>
        <button>
          {{loading ? 'Loading ...' : 'Update'}}
        </button>
      </div>

      <div>
        <button>
          退出登录
        </button>
      </div>
    </div>
  `
})
export class AccountComponent implements OnInit {
  loading = false;
  profile: Profile | undefined;

  @Input() session: Session | undefined;

  constructor(private readonly supabase: SupabaseService) { }

  ngOnInit() {
    this.getProfile();
  }

  async getProfile() {
    try {
      this.loading = true;
      let {data: profile, error, status} = await this.supabase.profile;

      if (error && status !== 406) {
        throw error;
      }

      if (profile) {
        this.profile = profile;
      }
    } catch (error:any) {
      alert(error.message)
    } finally {
      this.loading = false;
    }
  }

  async updateProfile(username: string, website: string, avatar_url: string = '') {
    try {
      this.loading = true;
      await this.supabase.updateProfile({username, website, avatar_url});
      alert("修改成功")
    } catch (error:any) {
      alert(error.message);
    } finally {
      this.loading = false;
    }
  }

  async signOut() {
    await this.supabase.signOut();
  }
}
Copier après la connexion
Copier après la connexion

🎜Définir le composant de connexion🎜🎜🎜🎜🎜Configurons un composant angulaire pour gérer Connectez-vous et inscrivez-vous. Nous utiliserons Magic Links pour que les utilisateurs puissent se connecter en utilisant leur adresse e-mail sans avoir à utiliser de mot de passe. Créez un 🎜AuthComponent à l'aide des commandes Angular CLI. 🎜 ng g c auth🎜🎜src/app/auth/auth.component.ts🎜rrreee

🎜Page d'informations sur l'utilisateur🎜🎜🎜Une fois l'utilisateur connecté , nous pouvons être autorisés à modifier les détails de leur profil et à gérer leur compte. Créez un 🎜AccountComponent à l'aide des commandes Angular CLI. 🎜 ng g c account🎜🎜src/app/account/account.component.ts🎜rrreee🎜🎜Modifiez le fichier d'entrée du projet🎜🎜🎜Maintenant que tous les composants sont prêts, mettons à jour 🎜AppComponent🎜 :🎜

src/app/app.component.ts

import {Component, OnInit} from '@angular/core';
import {SupabaseService} from "./supabase.service";

@Component({
  selector: 'app-root',
  template: `
  <div>
    <app-account></app-account>
    <ng-template>
      <app-auth></app-auth>
    </ng-template>
  </div>
  `
})
export class AppComponent implements OnInit {
  session = this.supabase.session;

  constructor(private readonly supabase: SupabaseService) { }

  ngOnInit() {
    this.supabase.authChanges((_, session) => this.session = session);
  }
}
Copier après la connexion
Copier après la connexion

完成后,在终端窗口中运行它:

npm run start
Copier après la connexion
Copier après la connexion

然后打开浏览器到 http://localhost:4200,你应该会看到完整的应用程序。

实现:上传头像及更新用户信息

每个 MemFire Cloud项目都配置了存储,用于管理照片和视频等大文件。

创建上传小组件

让我们为用户创建一个头像,以便他们可以上传个人资料照片。使用Angular CLI 命令创建AvatarComponent 。 ng g c avatar

src/app/avatar/avatar.component.ts

import {Component, EventEmitter, Input, Output} from '@angular/core';
import {SupabaseService} from "../supabase.service";
import {DomSanitizer, SafeResourceUrl} from "@angular/platform-browser";

@Component({
  selector: 'app-avatar',
  template: `
    <div>
      <img  alt="Parlons de la façon de créer des applications angulaires à l'aide de MemFire ​​​​Cloud" >
</div>
    <div></div>
    <div>
      <label>
        {{uploading ? 'Uploading ...' : 'Upload'}}
      </label>
      <input>
    </div>
  `,
})
export class AvatarComponent {
  _avatarUrl: SafeResourceUrl | undefined;
  uploading = false;

  @Input()
  set avatarUrl(url: string | undefined) {
    if (url) {
      this.downloadImage(url);
    }
  };

  @Output() upload = new EventEmitter<string>();

  constructor(
    private readonly supabase: SupabaseService,
    private readonly dom: DomSanitizer
  ) { }

  async downloadImage(path: string) {
    try {
      const {data} = await this.supabase.downLoadImage(path);
       if (data instanceof Blob) {
        this._avatarUrl = this.dom.bypassSecurityTrustResourceUrl(
          URL.createObjectURL(data)
        );
      }
    } catch (error:any) {
      console.error('下载图片出错: ', error.message);
    }
  }

  async uploadAvatar(event: any) {
    try {
      this.uploading = true;
      if (!event.target.files || event.target.files.length === 0) {
        throw new Error('必须选择要上载的图像。');
      }

      const file = event.target.files[0];
      const fileExt = file.name.split('.').pop();
      const fileName = `${Math.random()}.${fileExt}`;
      const filePath = `${fileName}`;

      await this.supabase.uploadAvatar(filePath, file);
      this.upload.emit(filePath);
      this.downloadImage(filePath)
    } catch (error:any) {
      alert(error.message);
    } finally {
      this.uploading = false;
    }
  }
}</string>
Copier après la connexion
Copier après la connexion

然后我们可以在AccountComponent html 模板的顶部添加小部件:

src/app/account/account.component.ts

import {Component, Input, OnInit} from '@angular/core';
import {Profile, SupabaseService} from "../supabase.service";
import {Session} from "@supabase/supabase-js";

@Component({
  selector: 'app-account',
  template: `
      <app-avatar>
    </app-avatar>
    <div>
      <div>
        <label>邮箱</label>
        <input>
      </div>
      <div>
        <label>名称</label>
        <input>
      </div>
      <div>
        <label>网址</label>
        <input>
      </div>

      <div>
        <button>
          {{loading ? 'Loading ...' : 'Update'}}
        </button>
      </div>

      <div>
        <button>
          退出登录
        </button>
      </div>
    </div>
  `
})
export class AccountComponent implements OnInit {
  loading = false;
  profile: Profile | undefined;

  @Input() session: Session | undefined;

  constructor(private readonly supabase: SupabaseService) { }

  ngOnInit() {
    this.getProfile();
  }

  async getProfile() {
    try {
      this.loading = true;
      let {data: profile, error, status} = await this.supabase.profile;

      if (error && status !== 406) {
        throw error;
      }

      if (profile) {
        this.profile = profile;
      }
    } catch (error:any) {
      alert(error.message)
    } finally {
      this.loading = false;
    }
  }

  async updateProfile(username: string, website: string, avatar_url: string = '') {
    try {
      this.loading = true;
      await this.supabase.updateProfile({username, website, avatar_url});
      alert("修改成功")
    } catch (error:any) {
      alert(error.message);
    } finally {
      this.loading = false;
    }
  }

  async signOut() {
    await this.supabase.signOut();
  }
}
Copier après la connexion
Copier après la connexion

恭喜!在这个阶段,您拥有一个功能齐全的应用程序!

更多编程相关知识,请访问:编程视频!!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:juejin.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!