使用Svelte从API正确处理错误(Rails)

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

我正在开发一个Svelte前端应用程序,该应用程序与Rails API服务器进行通信。我喜欢Rails的抽象方式(尤其是使用simple_form gem),并且希望为Svelte带来一些想法。我遇到的特定问题是如何将来自Rails服务器的错误与苗条的输入相关联]

首先,我从服务器调整了错误响应;通常,它们看起来像这样:

{ errors: 
  { generic: [<messages without association with particular field>], 
    email: ["Already taken", <msg_2>, ...], 
    password: ["Too short", ...],
    field_N: [...]
  }
}

generic错误可以是“无效的登录凭据”,“您的帐户被锁定”,“内部服务器错误”等。其他错误必须与表单字段相关,并且必须显示在它们旁边。

这是我目前的做法signup.svelte

<script>
let email;
let password;
function registerRequest() {
  let regURL = baseURL+'/api/users/';
  let data = {"user": {"email": email, "password": password}};
  fetch(regURL, {
    method: 'POST',
    body: JSON.stringify(data),
    headers: {
      'Content-Type': 'application/json'
    }
  })
  .then(function(response) {
    if (!response.ok) {
      return response.json()
    } 
  })
  // if errors present then iterate through errors object
  .then(function(error) {
    // find id of the message field and insert actual messages
    for (let [key, value] of Object.entries(error.errors)) {
 document.getElementById(key).insertAdjacentHTML('beforeend',value);
    }
  });
}
</script>

<style> .errormessage { color: red; } </style>

<form class="col-sm-12 col-lg-6" on:submit|preventDefault={registerRequest}>
  <!-- here I need to create errormessage container for each field. -->
  <!-- first one is generic to display generic errors -->
  <div class="errormessage" id="generic"></div>

  <label for="UserEmail">Email address</label>
  <input type="email" class="form-control" id="UserEmail" aria-describedby="emailHelp" placeholder="Enter your email here..." bind:value={email}>
  <div class="errormessage" id="email"></div>

  <label for="UserPassword">Password</label>
  <input type="password" class="form-control" id="UserPassword" placeholder="...and your password here" bind:value={password}>
  <div class="errormessage" id="password"></div>

  <button type="submit" class="btn btn-primary">Register</button>
</form>

我想通过前端验证来统一上面的代码。如果显示errors对象-在带有错误的字段旁边显示消息。在我看来,使用getElementById是过大的。如果我的DOM从不重新加载,为什么要使用它?每次在input上它将搜索ID。也许应该是侦听器来侦听错误对象的更改?我试图将自定义event与Svelte绑定import { createEventDispatcher } from 'svelte';,但没有运气。

请帮助并分享您的想法。

javascript ruby-on-rails error-handling api-design svelte
1个回答
2
投票

您的直觉是正确的,在Svelte组件中使用getElementById会感到不舒服-通常Svelte希望您使代码成为代码[[declarative,其中DOM是状态的函数,而不是imperative您正在手动更改DOM。

对于错误消息,建议您在组件中使用errors变量。当服务器错误再次出现时,您可以将它们分配给errors,这将导致响应更新并重新呈现组件。这样,标记就可以知道在错误存在时呈现错误,而无需显式更改DOM。像这样的东西:

<script> let email; let password; // New `errors` variable. let errors = {}; function registerRequest() { // Reset the errors when the user submits a new request. errors = {}; let regURL = baseURL+'/api/users/'; let data = {"user": {"email": email, "password": password}}; fetch(regURL, { method: 'POST', body: JSON.stringify(data), headers: { 'Content-Type': 'application/json' } }) .then(function(response) { if (!response.ok) { return response.json() } }) .then(function(error) { // Just save the errors errors = e.errors; }); } </script> <style> .errormessage { color: red; } </style> <form class="col-sm-12 col-lg-6" on:submit|preventDefault={registerRequest}> <!-- first one is generic to display generic errors --> <!-- note the `|| []` part, which makes sure that `#each` won't throw an error when `errors.generic` doesn't exist --> {#each (errors.generic || []) as error} <div class="errormessage" id="generic">{error}</div> {/each} <label for="UserEmail">Email address</label> <input type="email" class="form-control" id="UserEmail" aria-describedby="emailHelp" placeholder="Enter your email here..." bind:value={email}> <!-- email errors --> {#each (errors.email || []) as error} <div class="errormessage" id="email">{error}</div> {/each} <label for="UserPassword">Password</label> <input type="password" class="form-control" id="UserPassword" placeholder="...and your password here" bind:value={password}> <!-- password errors --> {#each (errors.password || []) as error} <div class="errormessage" id="password">{error}</div> {/each} <button type="submit" class="btn btn-primary">Register</button> </form>

这里是一个Svelte REPL,该代码正常工作。希望能有所帮助!
© www.soinside.com 2019 - 2024. All rights reserved.