将后端 Java 代码连接到基于 Angular 的前端

问题描述 投票:0回答:0

我正在 JHipster 上制作一个网络应用程序,该网络应用程序是一个房间预订网络应用程序,允许用户预订房间。我面临的问题是关于我正在实施的签入功能。我创建了一个包含必要实体的 jdl(见下文)。

entity Booking {
    Title String required
    StartTime ZonedDateTime required
    EndTime ZonedDateTime required
    AttendeesNum Integer required
    GoogleId String
    CheckedIn Boolean required
}

entity Room {
    Location String required
    Name String required
    FloorNum Integer required
    Capacity Integer required
    HasScreen Boolean required
    HasWhiteBoard Boolean required
    CanVideoCall Boolean required
    CanAudioCall Boolean required
    Status RoomStatus required
}

问题出在后端java代码和我无法使其与我的前端通信。我将在下面附上代码,但我也会解释我的确切含义。我在 jhipster 模板中创建/编辑了 2 个 java 文件,其中一个是我创建的文件,名为:

BookingService.java 这是一个服务类,负责处理与预订相关的业务逻辑。目前,它只有一个方法 checkIn,用于登记预订。登记入住时,它会将预订的 checkedIn 属性设置为 true,并将房间状态更新为 IN_USE。

package aryan.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import aryan.domain.Booking;
import aryan.domain.Room;
import aryan.domain.enumeration.RoomStatus;
import aryan.repository.BookingRepository;
import aryan.repository.RoomRepository;
import aryant.web.rest.errors.ResourceNotFoundException;

@Service
@Transactional
public class BookingService {
    private final BookingRepository bookingRepository;
    private final RoomRepository roomRepository;

    public BookingService(BookingRepository bookingRepository, RoomRepository roomRepository) {
        this.bookingRepository = bookingRepository;
        this.roomRepository = roomRepository;
    }

    public Booking checkIn(Long bookingId) {
        Booking booking = bookingRepository.findById(bookingId).orElseThrow(() -> new ResourceNotFoundException("Booking not found"));
        booking.setCheckedIn(true);
        Room room = booking.getRoom();
        room.setStatus(RoomStatus.IN_USE);
        roomRepository.save(room);
        return bookingRepository.save(booking);
    }
}

另一个是默认配置中已有的文件,名为 BookingResource.java,它是一个 REST 控制器,用于管理 Web 应用程序中的预订。此类有多种方法来处理不同的 REST API 端点,例如创建新预订、更新现有预订、部分更新预订、获取所有预订或特定预订、删除预订以及登记预订。它还包括一个辅助方法 buildLocation,用于根据预订创建位置字符串。关于分享这段代码,我只会分享相关的部分和它的一大段代码

@RestController
@RequestMapping("/api")
@Transactional
public class BookingResource {

    private final UserService userService;
    private final BookingService bookingService;

    private final Logger log = LoggerFactory.getLogger(BookingResource.class);

    private static final String ENTITY_NAME = "booking";

    @Value("${jhipster.clientApp.name}")
    private String applicationName;

    private final BookingRepository bookingRepository;

    @Autowired
    public BookingResource(BookingRepository bookingRepository, UserService userService, BookingService bookingService) {
        this.bookingRepository = bookingRepository;
        this.userService = userService;
        this.bookingService = bookingService;
    }
    
    @PostMapping("/bookings/{id}/check-in")
       public ResponseEntity<Booking> checkIn(@PathVariable Long id) {
           Booking result = bookingService.checkIn(id);
           return ResponseEntity.ok().body(result);
    }

现在前端代码对我自己来说更容易理解了,我在 html 中实现了我必须创建一个按钮并在单击时将其链接到一个方法(onClick),该方法将在打字稿中并被调用,该方法是我苦苦挣扎的问题,这就是我将后端和前端连接在一起的意思。我该怎么做才能在单击签入按钮时与后端通信并更新数据库。我还将提供 html 和 ts 文件的相关部分。注意:签入按钮将处于模态状态。

HTML:

<ng-template #content let-modal>
      <div class="modal-header">
        <h4 class="modal-title">Booking Details</h4>
        <button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <!-- Add the booking details content from booking-detail.component.html here -->
        <div class="d-flex justify-content-center">
          <div class="col-8">
            <div *ngIf="booking">
              <h2 data-cy="bookingDetailsHeading"><span jhiTranslate="aryan.booking.detail.title">Booking</span></h2>

              <hr />

              <jhi-alert-error></jhi-alert-error>

              <jhi-alert></jhi-alert>

              <dl class="row-md jh-entity-details">
                <dt><span jhiTranslate="global.field.id">ID</span></dt>
                <dd>
                  <span>{{ booking.id }}</span>
                </dd>
                <dt><span jhiTranslate="aryan.booking.title">Title</span></dt>
                <dd>
                  <span>{{ booking.title }}</span>
                </dd>
                <dt><span jhiTranslate="aryan.booking.startTime">Start Time</span></dt>
                <dd>
                  <span>{{ booking.startTime | formatMediumDatetime }}</span>
                </dd>
                <dt><span jhiTranslate="aryan.booking.endTime">End Time</span></dt>
                <dd>
                  <span>{{ booking.endTime | formatMediumDatetime }}</span>
                </dd>
                <dt><span jhiTranslate="aryan.booking.attendeesNum">Attendees Num</span></dt>
                <dd>
                  <span>{{ booking.attendeesNum }}</span>
                </dd>
                <dt><span jhiTranslate="aryan.booking.googleId">Google ID</span></dt>
                <dd>
                  <span>{{ booking.googleId }}</span>
                </dd>
                <dt><span jhiTranslate="aryan.booking.checkedIn">Checked In</span></dt>
                <dd>
                  <span>{{ booking.checkedIn }}</span>
                </dd>
                <dt><span jhiTranslate="aryan.booking.room">Room</span></dt>
                <dd>
                  <div *ngIf="booking.room">
                    <a [routerLink]="['/room', booking.room.id, 'view']">{{ booking.room.id }}</a>
                  </div>
                </dd>
                <dt><span jhiTranslate="aryan.booking.user">User</span></dt>
                <dd>
                  <span>{{ booking.user?.id }}</span>
                </dd>
                <dt><span jhiTranslate="aryan.booking.attendee">Attendee</span></dt>
                <dd>
                  <span *ngFor="let attendee of booking.attendees; let last = last"> {{ attendee.login }}{{ last ? '' : ', ' }} </span>
                </dd>
              </dl>
            </div>
          </div>
        </div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" (click)=someMethod">Check In </button>
        <button type="button" class="btn btn-secondary" (click)="modal.close('Close click')">Close</button>
      </div>
    </ng-template>

TS:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Data, ParamMap, Router } from '@angular/router';
import { combineLatest, filter, Observable, switchMap, tap } from 'rxjs';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';

import { IBooking } from '../booking.model';
import { ASC, DESC, SORT, ITEM_DELETED_EVENT, DEFAULT_SORT_DATA } from 'app/config/navigation.constants';
import { EntityArrayResponseType, BookingService } from '../service/booking.service';
import { BookingDeleteDialogComponent } from '../delete/booking-delete-dialog.component';
import { SortService } from 'app/shared/sort/sort.service';



@Component({
  selector: 'jhi-booking',
  templateUrl: './booking.component.html',
})
export class BookingComponent implements OnInit {
  bookings?: IBooking[];
  isLoading = false;

  predicate = 'id';
  ascending = true;

  constructor(
    protected bookingService: BookingService,
    protected activatedRoute: ActivatedRoute,
    public router: Router,
    protected sortService: SortService,
    protected modalService: NgbModal
  ) {}

  trackId = (_index: number, item: IBooking): number => this.bookingService.getBookingIdentifier(item);
  booking: IBooking | null = null;

  ngOnInit(): void {
    this.load();
  }

  delete(booking: IBooking): void {
    const modalRef = this.modalService.open(BookingDeleteDialogComponent, { size: 'lg', backdrop: 'static' });
    modalRef.componentInstance.booking = booking;
    // unsubscribe not needed because closed completes on modal close
    modalRef.closed
      .pipe(
        filter(reason => reason === ITEM_DELETED_EVENT),
        switchMap(() => this.loadFromBackendWithRouteInformations())
      )
      .subscribe({
        next: (res: EntityArrayResponseType) => {
          this.onResponseSuccess(res);
        },
      });
  }

  load(): void {
    this.loadFromBackendWithRouteInformations().subscribe({
      next: (res: EntityArrayResponseType) => {
        this.onResponseSuccess(res);
      },
    });
  }

  navigateToWithComponentValues(): void {
    this.handleNavigation(this.predicate, this.ascending);
  }

  protected loadFromBackendWithRouteInformations(): Observable<EntityArrayResponseType> {
    return combineLatest([this.activatedRoute.queryParamMap, this.activatedRoute.data]).pipe(
      tap(([params, data]) => this.fillComponentAttributeFromRoute(params, data)),
      switchMap(() => this.queryBackend(this.predicate, this.ascending))
    );
  }

  protected fillComponentAttributeFromRoute(params: ParamMap, data: Data): void {
    const sort = (params.get(SORT) ?? data[DEFAULT_SORT_DATA]).split(',');
    this.predicate = sort[0];
    this.ascending = sort[1] === ASC;
  }

  protected onResponseSuccess(response: EntityArrayResponseType): void {
    const dataFromBody = this.fillComponentAttributesFromResponseBody(response.body);
    this.bookings = this.refineData(dataFromBody);
  }

  protected refineData(data: IBooking[]): IBooking[] {
    return data.sort(this.sortService.startSort(this.predicate, this.ascending ? 1 : -1));
  }

  protected fillComponentAttributesFromResponseBody(data: IBooking[] | null): IBooking[] {
    return data ?? [];
  }

  protected queryBackend(predicate?: string, ascending?: boolean): Observable<EntityArrayResponseType> {
    this.isLoading = true;
    const queryObject = {
      eagerload: true,
      sort: this.getSortQueryParam(predicate, ascending),
    };
    return this.bookingService.query(queryObject).pipe(tap(() => (this.isLoading = false)));
  }

  protected handleNavigation(predicate?: string, ascending?: boolean): void {
    const queryParamsObj = {
      sort: this.getSortQueryParam(predicate, ascending),
    };

    this.router.navigate(['./'], {
      relativeTo: this.activatedRoute,
      queryParams: queryParamsObj,
    });
  }

  protected getSortQueryParam(predicate = this.predicate, ascending = this.ascending): string[] {
    const ascendingQueryParam = ascending ? ASC : DESC;
    if (predicate === '') {
      return [];
    } else {
      return [predicate + ',' + ascendingQueryParam];
    }
  }

  open(content: any, booking: IBooking): void {
    this.booking = booking;
    this.modalService.open(content, { ariaLabelledBy: 'modal-basic-title' }).result.then(
      result => {
        // Handle the result here
      },
      reason => {
        // Handle the reason for dismissal here
      }
    );
  }
  previousState(): void {
    window.history.back();
  }
}

我已经尝试创建我的多个方法,其中涉及调用 BookingService.java 中的方法,但我仍然遇到错误。这是我的第一个项目,所以我对这一切还很陌生。我期望发生的事情是当我运行 ./mvnw 时,代码将编译它所做的并转到签入按钮并单击该按钮,签入字段将从假变为真。实际发生的是代码构建成功,但是当我点击签入时,我会在 intelliJ 终端中收到一堆错误,说它失败了

java html typescript jhipster
© www.soinside.com 2019 - 2024. All rights reserved.