Last active
February 19, 2019 08:54
-
-
Save gistlyn/c4b6391281226b05993d92e7cf8b0359 to your computer and use it in GitHub Desktop.
Client Ajax Contact Form using TypeScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{{ `/client-ts/login?continue=${PathInfo}` | |
| redirectIfNotAuthenticated }} | |
<div style="text-align:right"> | |
<small class="text-muted"> | |
{{ userSession.DisplayName }} | |
| <a href="/auth/logout?continue=/client-ts/">Sign Out</a> | |
</small> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{{ 'requires-auth' | partial }} | |
<h3>Add new Contact</h3> | |
<form action="/contacts" method="post" class="col-lg-4"> | |
<div class="form-group" data-validation-summary="title,name,color,filmGenres,age,agree"></div> | |
<div class="form-group"> | |
<div class="form-check"> | |
{{#each contactTitles}} | |
<div class="custom-control custom-radio custom-control-inline"> | |
<input type="radio" id="title-{{Key}}" name="title" value="{{Key}}" class="custom-control-input"> | |
<label class="custom-control-label" for="title-{{Key}}">{{Value}}</label> | |
</div> | |
{{/each}} | |
</div> | |
</div> | |
<div class="form-group"> | |
<label for="name">Full Name</label> | |
<input class="form-control" id="name" name="name" type="text" placeholder="Name"> | |
<small id="name-help" class="text-muted">Your first and last name</small> | |
</div> | |
<div class="form-group"> | |
<label class="form-label" for="color">Favorite color</label> | |
<select id="color" name="color" class="col-4 form-control"> | |
<option value=""></option> | |
{{#each contactColors}} | |
<option value="{{Key}}">{{Value}}</option> | |
{{/each}} | |
</select> | |
</div> | |
<div class="form-group"> | |
<label class="form-check-label">Favorite Film Genres</label> | |
<div class="form-check"> | |
{{#each contactGenres}} | |
<div class="custom-control custom-checkbox"> | |
<input type="checkbox" id="filmGenres-{{it}}" name="filmGenres" value="{{it}}" class="form-check-input"> | |
<label class="form-check-label" for="filmGenres-{{it}}">{{it}}</label> | |
</div> | |
{{/each}} | |
</div> | |
</div> | |
<div class="form-group"> | |
<input class="form-control col-3" name="age" type="number" min="13" placeholder="Age"> | |
</div> | |
<div class="form-group"> | |
<div class="form-check"> | |
<input class=" form-check-input" id="agree" name="agree" type="checkbox" value="true"> | |
<label class="form-check-label" for="agree">Agree to terms and conditions</label> | |
</div> | |
</div> | |
<div class="form-group"> | |
<button class="btn btn-primary" type="submit">Add Contact</button> | |
<a href="/client-ts/contacts/">reset</a> | |
</div> | |
</form> | |
<table id="results"></table> | |
{{#capture appendTo scripts}} | |
<script>var CONTACTS = {{ sendToGateway('GetContacts') | map => it.Results | json }};</script> | |
{{/capture}} | |
{{#raw appendTo scripts}} | |
<script src="index.js"></script> | |
{{/raw}} | |
{{ htmlError }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { bootstrapForm, bindHandlers, JsonServiceClient } from "@servicestack/client"; | |
import {Contact, DeleteContact, GetContact, GetContacts} from "../../../dtos"; | |
declare var CONTACTS:Contact[]; | |
const client = new JsonServiceClient(); | |
const form = document.querySelector("form")!; | |
bootstrapForm(form,{ | |
success: function (r:{result:Contact}) { | |
form.reset(); | |
CONTACTS.push(r.result); | |
render(); | |
} | |
}); | |
bindHandlers({ | |
deleteContact: async function(id:number) { | |
if (!confirm('Are you sure?')) | |
return; | |
await client.delete(new DeleteContact({ id })); | |
const response = await client.get(new GetContacts()); | |
CONTACTS = response.results; | |
render(); | |
} | |
}); | |
const contactRow = (contact:Contact) => | |
`<tr style="background:${contact.color}"> | |
<td>${contact.title} ${contact.name} (${contact.age})</td> | |
<td><a href="/client-ts/contacts/${contact.id}/edit">edit</a></td> | |
<td><button class="btn btn-sm btn-primary" data-click="deleteContact:${contact.id}">delete</button></td> | |
</tr>`; | |
function render() { | |
let sb = ""; | |
if (CONTACTS.length > 0) { | |
for (let i=0; i<CONTACTS.length; i++) { | |
sb += contactRow(CONTACTS[i]) | |
} | |
} else { | |
sb = "<tr><td>There are no contacts.</td></tr>"; | |
} | |
document.querySelector("#results")!.innerHTML = `<tbody>${sb}</tbody>`; | |
} | |
render(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment