Отправить данные формы с выбранным раскрывающимся списком

Я хочу обновить данные формы, когда я обновляю раскрывающийся список выберите и нажмите кнопку отправки. Я попытался реализовать это:

Конструктор:

export class Contract {
  constructor(
    public id: string,
    public enabled: boolean,
    public name: string,
    public merchant_id: number,    
    public gateway: string,
    public descriptor: string
  ) {}
}

Услуга:

@Injectable({
  providedIn: 'root'
})
export class ContractService {

  constructor(private http: HttpClient) {
  }

  search(filter: ContractFilter, page: number, size: number): Observable<PagedResult<Contract>> {
    let params = this.buildFilterParams(filter);
    let pagedFilter = HttpUtils.appendPageParams(params, page, size);

    return this.http.get<PagedResult<Contract>>(environment.api.urls.contracts.base, {params: pagedFilter});
  }

  private buildFilterParams(filter: ContractFilter): HttpParams {
    let params = new HttpParams();

    if (filter.name) {
      params = params.append('name', filter.name);
    }
    if (filter.id) {
      params = params.append('id', filter.id);
    }

    if (filter.from) {
      params = params.append('from', DateUtil.offsetDate(filter.from.toISOString()));
    }

    if (filter.to) {
      params = params.append('to', DateUtil.offsetDate(filter.to.toISOString()));
    }
    return params;
  }

  save(contract: Contract) {
    return this.http.post(environment.api.urls.contracts.base, contract);
  }

  persist(contract: Contract) {
    return this.http.post(environment.api.urls.contracts.persist(contract.id), contract);
  }

  get(contractId: string): Observable<Contract> {
    return this.http.get<Contract>(environment.api.urls.contracts.get(contractId));
  }

  export() {
    return this.http.get(environment.api.urls.contracts.export,  { responseType: 'blob' });
  }
}

Составная часть:

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

  contract: Contract = new Contract(null, null, null, null, null);
  merchants: MerchantList[];

  edit = false;

  valueExists = false;

  constructor(private contractService: ContractService,
              private merchantService: MerchantService,
              private router: Router,
              private route: ActivatedRoute) {
  }

  ngOnInit() {

    this.route.params.pipe(
      flatMap(params => {
        if (params['id']) {
          return this.contractService.get(params['id']);
        } else {
          return of(null);
        }
      })
    ).subscribe(value => {
      if (value != null) {
        this.contract = value;
        this.edit = true;
      }
    });

    this.merchantService.getMerchantsList()
     .subscribe(value => {
        if (value != null) {
          this.merchants = value;
        }
    });
  }

  clear() {
    this.contract.name = null;
  }

  submit() {
    if (this.edit) {
      this.contractService.persist(this.contract).subscribe(() => {
        this.router.navigate(['panel', 'contracts', 'list']);
      })
    } else {
      this.contractService.save(this.contract).subscribe(() => {
          this.router.navigate(['panel', 'contracts', 'list']);
        },
        error => this.handleError(error.error));
    }
  }

  handleError(error: string) {
    if (error === 'TRANSACTION_EXISTS') {
      this.valueExists = true;
    }
  }
}

HTML код:

<h1 class = "title">New Contract</h1>

<form class = "grid-wrapper" #f = "ngForm">
  <div *ngIf = "edit" class = "form-group id">
    <label for = "id">Transaction ID</label>
    <input id = "id" type = "text" name = "id" class = "form-control" disabled [(ngModel)] = "contract.id">
  </div>

  <div class = "form-group name">
    <label for = "name">Contract name</label>
    <input id = "name" type = "text" name = "name" class = "form-control" required [(ngModel)] = "contract.name">
  </div>

  <div class = "form-group type">
    <div class = "input-group-prepend">
      <label for = "type">Merchant</label>
    </div>
    <select class = "custom-select" name = "type" [(ngModel)] = "contract.merchant_id" id = "merchant_id" required>
      <option selected>Please Select...</option>
      <option [value] = "merchant.id" *ngFor = "let merchant of merchants">{{ merchant.name }}</option>
    </select>
  </div>

  <div class = "btn-row">
    <button class = "btn btn-primary" [disabled] = "f.invalid" (click) = "submit()">Submit</button>
    <button class = "btn btn-secondary" (click) = "clear()">Clear</button>
  </div>

</form>

Строки в поле ввода обновляются, но я не могу понять, почему, когда я выбираю другое значение из раскрывающегося списка, оно не обновляется.

Можете ли вы дать мне совет, в чем я ошибаюсь?

Код, который вы предоставили, мне подходит. Вы тестировали API, которые вызываются в методах сохранения, сохранения и получения ContractService, без интеграции с пользовательским интерфейсом? Они работают особенно с merchant_id?

Yas Ikeda 16.11.2018 22:55

в бэкэнде я получаю эту ошибку pastebin.com/35z1vzvx

Peter Penzov 16.11.2018 23:01

это выглядит ошибкой из-за сохранения данных. В соответствии с ситуацией, которую вы объяснили в своем вопросе, это может быть ошибка, возникающая при обновлении merchant_id в базе данных. Оставьте пользовательский интерфейс как есть, и сначала вы должны решить проблему.

Yas Ikeda 17.11.2018 00:50

Как говорится в предупреждающем сообщении после сообщения об ошибке, в вашем коде есть проблема, связанная с какой-то блокировкой. Я не уверен в спящем режиме, но думаю, что ответ здесь может быть связано с вашей проблемой. Я думаю, что query.setLockMode(LockModeType.PESSIMISTIC_WRITE); и entityManager.lock(tsn, LockModeType.PESSIMISTIC_WRITE); - суть ответа.

Yas Ikeda 17.11.2018 00:52
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
2
4
2 171
3

Ответы 3

ссылка на https://angular.io/guide/forms Каждый элемент ввода имеет свойство name, которое требуется формам Angular для регистрации элемента управления в форме.

ваша проблема в шаблоне HTML вы должны изменить свойство name с "type" на "merchant_id", как в вашей модели.

<select class = "custom-select" name = "merchant_id" [(ngModel)] = "contract.merchant_id" id = "merchant_id" required>
  <option selected>Please Select...</option>
  <option [value] = "merchant.id" *ngFor = "let merchant of merchants">{{ merchant.name }}</option>
</select>

как генерал,

HTML

<select [(ngModel)] = "selectedOption" name = "first" (change) = "selected()">
   <option *ngFor = "let o of options">
      {{o.name}}
   </option>
</select>

Машинопись

selectedOption: string;
options = [
    { name: "option1", value: 1 },
    { name: "option2", value: 2 }
]

selected(){
   console.info(this.selectedOption)
}

В вашем случае попробуйте это,

HTML

<select class = "custom-select" name = "type" [(ngModel)] = "contract.merchant_id" id = "merchant_id" (ngModelChange) = "onChange($event)" required>
      <option selected>Please Select...</option>
      <option [value] = "merchant.id" *ngFor = "let merchant of merchants">{{ merchant.name }}</option>
</select>

Машинопись

onChange(merchant) {
   console.info(merchant);
}

Хорошо, но я не понимаю, как это может решить проблему с кодом.

Peter Penzov 09.11.2018 12:00

нет, наверное потому, что логика для обновления SQL не реализована?

Peter Penzov 09.11.2018 12:35

Можете ли вы добавить свою модель данных?

Dhanika 09.11.2018 12:54

Пост обновлен. Что-нибудь еще, что вы хотели бы увидеть?

Peter Penzov 09.11.2018 13:03

Я думаю, что [(ngModel)] = "contract.merchant_id" должно быть [(ngModel)] = "contract.id"

Dhanika 09.11.2018 13:05

Позвольте нам продолжить обсуждение в чате.

Dhanika 09.11.2018 13:13

Давайте оставим это простым и внесем изменения в select box как - Используйте merchant в качестве значения вместо merchant id. Он обновит весь объект merchant, а остальная часть field будет обновлена ​​автоматически.

html

 <select class = "custom-select" name = "type" 
        [(ngModel)] = "contract" 
        [compareWith] = "compareFn"
         id = "merchant_id" required>
      <option selected>Please Select...</option>
      <option [ngValue] = "merchant" *ngFor = "let merchant of merchants">{{ merchant.name }}</option>
    </select>

ts

compareFn(a, b) {
    if (!a || !b) {
      return false;
    } else {
      return a.merchant_id === b.merchant_id; //you can use other property also
    }
  }

Другие вопросы по теме