在Angular中动态更新OG元标签

5
我希望分享一些来自API的动态内容到WhatsApp,因此我在我的component.ts文件中使用了angular Meta类来更新index.html中默认meta标签的属性,以展示动态内容。
当我浏览到我想要更新og meta标签的特定页面时,该标签已经添加到DOM中。但是当我分享相同的页面URL到WhatsApp时,动态内容并没有出现。 index.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>DMK Youth Wing</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <!-- og meta tags for link share  -->
  <meta property="og:title" content="" />
  <meta property="og:description" content="" />
  <meta property="og:url" content="https://www.youthwingdmk.in/" />
  <meta property="og:image" content="https://www.myhealthunlimited.com/wp-content/uploads/2016/07/300x200.png" />

  <link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css"
    integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous" />
  <link rel="icon" type="image/x-icon" href="./assets/images/Youth wing logo2.png">
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Mukta+Malar:wght@300;400;500;600;700;800&display=swap"
    rel="stylesheet">

  <!-- twitter plugin -->
  <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
  <link rel="preconnect" href="https://fonts.gstatic.com">
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

  <!-- Animation -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
  <link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
</head>

<body class="scrollable">
  <app-root></app-root>
  <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
    integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
    crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
    integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
    crossorigin="anonymous"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
    integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
    crossorigin="anonymous"></script>
  <script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>

</body>
</html>

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule, Meta } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { LayoutModule } from '@angular/cdk/layout';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { HttpClient, HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { ApplicationFormComponent } from './components/application-form/application-form.component';
import { ContactFormComponent } from './components/contact-form/contact-form.component';
import { PageNotFoundComponent } from './components/page-not-found/page-not-found.component';
import { HomeComponent } from './components/home/home.component';
import { NavBarComponent } from './components/nav-bar/nav-bar.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { InputComponent } from './components/input/input.component';
import { HistoryFeedComponent } from './components/home/history-feed/history-feed.component';
import { HistoryComponent } from './components/home/history-feed/history/history.component';
import { FeedComponent } from './components/home/history-feed/feed/feed.component';
import { GalleryComponent } from './components/home/gallery/gallery.component';
import { YouthTeamComponent } from './components/home/youth-team/youth-team.component';
import { ReportsComponent } from './components/home/reports/reports.component';
import { FooterComponent } from './components/footer/footer.component';
import { NgSelectModule } from '@ng-select/ng-select';
import { SelectComponent } from './components/select/select.component';
import { NgxSpinnerModule } from 'ngx-spinner';
import { ToastrModule } from 'ngx-toastr';
import { SlickCarouselModule } from 'ngx-slick-carousel';
import { ErrrorInterceptor } from './interceptors/error/errror.interceptor';
import { SocialMediaComponent } from './components/nav-bar/social-media/social-media.component';
import { SlickCarouselComponent } from './components/home/gallery/slick-carousel/slick-carousel.component';
import { BannerComponent } from './components/home/banner/banner.component';
import { LoginModalComponent } from './components/home/youth-team/login-modal/login-modal.component';
import { PubCardComponent } from './components/publications/pub/pub-card/pub-card.component';
import { PubPageComponent } from './components/publications/pub/pub-page/pub-page.component';
import { PubDetailsComponent } from './components/publications/pub/pub-details/pub-details.component';
import { PubListComponent } from './components/publications/pub/pub-list/pub-list.component';
import { PaymentComponent } from './components/home/payment/payment.component';
import { LibraryComponent } from './components/library/library.component';
import { MatTableModule } from '@angular/material/table';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatSortModule } from '@angular/material/sort';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { PhotosComponent } from './components/photos/photos.component';
import { YoutubeVideosComponent } from './components/youtube-videos/youtube-videos.component';
import { NgImageFullscreenViewModule } from 'ng-image-fullscreen-view';
import { LoginComponent } from './login/login.component';
import { BeneficiariesComponent } from './components/home/beneficiaries/beneficiaries.component';
import { OrgChartComponent } from './components/home/youth-team/org-chart/org-chart.component';
import { OrgTreeComponent } from './components/org-tree/org-tree.component';
import { LibrarybookdetailComponent } from './components/library/librarybookdetail/librarybookdetail.component';
import { LibraryhashComponent } from './components/library/libraryhash/libraryhash.component';
import { LibraryCommentDetailsComponent } from './components/library/library-comment-details/library-comment-details.component';

import { ShareButtonsModule } from 'ngx-sharebuttons/buttons';
import { ShareIconsModule } from 'ngx-sharebuttons/icons';

@NgModule({
  declarations: [
    AppComponent,
    ApplicationFormComponent,
    ContactFormComponent,
    PageNotFoundComponent,
    HomeComponent,
    NavBarComponent,
    InputComponent,
    HistoryFeedComponent,
    HistoryComponent,
    FeedComponent,
    GalleryComponent,
    YouthTeamComponent,
    ReportsComponent,
    FooterComponent,
    SelectComponent,
    SocialMediaComponent,
    SlickCarouselComponent,
    BannerComponent,
    LoginModalComponent,
    PubCardComponent,
    PubPageComponent,
    PubDetailsComponent,
    PubListComponent,
    PaymentComponent,
    LibraryComponent,
    PhotosComponent,
    YoutubeVideosComponent,
    LoginComponent,
    BeneficiariesComponent,
    OrgChartComponent,
    OrgTreeComponent,
    LibrarybookdetailComponent,
    LibraryhashComponent,
    LibraryCommentDetailsComponent,
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    AppRoutingModule,
    ReactiveFormsModule,
    FormsModule,
    LayoutModule,
    NgbModule,
    HttpClientModule,
    NgSelectModule,
    NgxSpinnerModule,
    ToastrModule.forRoot({
      timeOut: 1500,
      positionClass: 'toast-top-right',
      preventDuplicates: true,
    }),
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
      }
    }),
    SlickCarouselModule,
    MatTableModule,
    MatPaginatorModule,
    MatSortModule,
    MatFormFieldModule,
    MatInputModule,
    NgImageFullscreenViewModule,
    ShareButtonsModule.withConfig({
      debug: true
    }),
    ShareIconsModule

  ],
  providers: [
    Meta
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

// required for AOT compilation
export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {
  return new TranslateHttpLoader(http);
}

pub-details.component.ts

import { Component, OnInit } from '@angular/core';
import { Meta } from '@angular/platform-browser';
import { ActivatedRoute, Data, NavigationExtras, Router } from '@angular/router';
import { HttpService } from 'src/app/services/http.service';


@Component({
  selector: 'app-pub-details',
  templateUrl: './pub-details.component.html',
  styleUrls: ['./pub-details.component.scss']
})
export class PubDetailsComponent implements OnInit {

  reportData = [];
  reportId: number;

  constructor(
    private service: HttpService,
    private activeRoute: ActivatedRoute,
    private meta: Meta
  ) { }

  ngOnInit(): void {

   this.activeRoute.queryParams.subscribe(params => {
      this.reportId = +params.Id;
    }
    this.getSpecificReport(this.reportId);
  }

  getSpecificReport(id) {
    this.service.getSpecificReport(id).subscribe((res: any) => {
      this.reportData = res.Data[0].Data;

      this.meta.updateTag(
        { property: 'og:title', content: this.reportData['PostTitle'] },
      );
      this.meta.updateTag(
        { property: 'og:description', content: this.reportData['PostTitle'] },
      );
    }, (err) => { }
    );
  }

}

HTML DOM更新meta标签后(内容更新) 输入图片描述

将相同URL分享到WhatsApp(内容未更新) 输入图片描述


您可以使用共享调试器来查找问题。 - Pieterjan
1个回答

1
你可以在这里尝试meta标签验证器:https://thumbsmith.com/validator/ 另外,请确保动态(每个页面)内容可在服务器端访问,而不仅仅是客户端。
一个快速的技巧,用于轻松检查服务器端HTML代码,就是在Chrome中在URL前面添加view-source:或右键点击>查看页面源代码。

2
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community
@Alexandre Lotte,我该如何在服务器端提供内容?通常情况下,Angular应用程序是在客户端填充数据的,或者我理解错了吗? - Klops
你需要Angular SSR(Universal):https://angular.io/guide/universal - Borongaj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接