Skip to content

Commit 928a5fd

Browse files
authored
Append query params to url if provided (#28)
If a user wants to request a url with query params, they have to build the URL with query params on their own with `URLSearchParams` or something similar. For example, a dynamic country / state select you might do the following to update the state select field after choosing a country: ```javascript async updateStateSelect(event) { const value = event.target.selectedOptions[0].value const query = new URLSearchParams({ country: value }) const response = await get(`/addresses/states?${query}`, { responseKind: "turbo-stream" }) } ``` This PR adds a `query` option that will automatically be appended to the URL if provided. The above example can then become the following: ```javascript async updateStateSelect(event) { const response = await get("/addresses/states", { query: { country: event.target.selectedOptions[0].value }, responseKind: "turbo-stream" }) } ``` Both examples will make requests to `/addresses/states?country=us`. I also updated the README to document all the request options a bit clearer (and documented `query`). Originally, I named the option `params` but thought `query` was clearer.
1 parent 1e04b60 commit 928a5fd

File tree

2 files changed

+47
-18
lines changed

2 files changed

+47
-18
lines changed

README.md

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,33 +54,44 @@ async myMethod () {
5454
}
5555
```
5656

57-
#### Request body
57+
#### Request Options
5858

59-
Instead of stringify the body of a request which the content type is `application/json`, you can just pass the javascript object as the body of the request and Request.JS will stringify it for you.
59+
You can pass options to a request as the last argument. For example:
6060

61-
```js
62-
import { post } from '@rails/request.js'
63-
64-
...
65-
66-
async myMethod () {
67-
const response = await post('localhost:3000/my_endpoint', { body: { name: 'Request.JS' } })
68-
if (response.ok) {
69-
...
70-
}
71-
}
61+
```javascript
62+
post("/my_endpoint", {
63+
body: {},
64+
contentType: "application/json",
65+
headers: {},
66+
query: {},
67+
responseKind: "html"
68+
})
7269
```
7370

74-
### responseKind
71+
##### body
7572

76-
You can provide this option to specify which kind of response will be accepted. Default is `html`.
73+
This is the `body` for POST requests. You can pass in a Javascript object, FormData, Files, strings, etc.
7774

78-
Options are `html`, `turbo-stream`, `json`.
75+
Request.js will automatically JSON stringify the `body` if the content type is `application/json`.
7976

80-
### contentType
77+
##### contentType
8178

8279
When provided this value will be sent in the `Content-Type` header. When not provided Request.JS will send nothing when the `body` of the request is `null` or an instance of `FormData`, when the `body` is an instance of a `File` then the type of the file will be sent and `application/json` will be sent if none of the prior conditions matches.
8380

81+
##### headers
82+
83+
Adds additional headers to the request. `X-CSRF-Token` and `Content-Type` are automatically included.
84+
85+
##### query
86+
87+
Appends query parameters to the URL. Query params in the URL are preserved and merged with the query options.
88+
89+
##### responseKind
90+
91+
Specifies which response format will be accepted. Default is `html`.
92+
93+
Options are `html`, `turbo-stream`, `json`.
94+
8495
#### Turbo Streams
8596

8697
Request.JS will automatically process Turbo Stream responses. Ensure that your Javascript sets the `window.Turbo` global variable:

src/fetch_request.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import { getCookie, compact, metaContent } from './lib/utils'
55
export class FetchRequest {
66
constructor (method, url, options = {}) {
77
this.method = method
8-
this.url = url
98
this.options = options
9+
this.originalUrl = url
1010
}
1111

1212
async perform () {
@@ -93,6 +93,24 @@ export class FetchRequest {
9393
return this.options.body
9494
}
9595

96+
get query () {
97+
const originalQuery = (this.originalUrl.split('?')[1] || '').split('#')[0]
98+
const params = new URLSearchParams(originalQuery)
99+
100+
if (this.options.query) {
101+
for (const [key, value] of Object.entries(this.options.query)) {
102+
params.append(key, value)
103+
}
104+
}
105+
106+
const query = params.toString()
107+
return (query.length > 0 ? `?${query}` : '')
108+
}
109+
110+
get url () {
111+
return this.originalUrl.split('?')[0] + this.query
112+
}
113+
96114
get responseKind () {
97115
return this.options.responseKind || 'html'
98116
}

0 commit comments

Comments
 (0)