SharePoint Saturday Help Desk Code
Posted by Isaac Sogunro
Today (6/1/2019) I gave my first presentation at SharePoint Saturday in Reston, VA. My presentation was on how to use VUE.js with SharePoint. I had created a simple help desk form to explain how Vue instance, Vue-Directives, Methods, and life cycle hooks (specifically ‘Created’) worked. Below is the code I promised to share.
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
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> | |
<!– Special version of Bootstrap that only affects content wrapped in .bootstrap-iso –> | |
<link rel="stylesheet" href="https://formden.com/static/cdn/bootstrap-iso.css" /> | |
<!– Inline CSS based on choices in "Settings" tab –> | |
<style>.bootstrap-iso .formden_header h2, .bootstrap-iso .formden_header p, .bootstrap-iso form{font-family: Arial, Helvetica, sans-serif; color: #54787c}.bootstrap-iso form button, .bootstrap-iso form button:hover{color: #ffffff !important;}.bootstrap-iso .form-control:focus { border-color: #e9666c; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(233, 102, 108, 0.6); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(233, 102, 108, 0.6);} .asteriskField{color: red;}.bootstrap-iso form .input-group-addon {color:#555555; background-color: #f7efef; border-radius: 4px; padding-left:12px}</style> | |
<!– HTML Form (wrapped in a .bootstrap-iso div) –> | |
<div id="app"> | |
<p v-if="errors.length" style="color:red"> | |
<b>Please correct the following error(s):</b> | |
<ul> | |
<li v-for="error in errors">{{ error }}</li> | |
</ul> | |
</p> | |
<div class="bootstrap-iso"> | |
<div class="container-fluid"> | |
<div class="row"> | |
<div class="col-md-6 col-sm-6 col-xs-12"> | |
<!– Start Your Name Field–> | |
<div class="form-group "> | |
<label class="control-label " for="name"> | |
Your Name * | |
</label> | |
<input class="form-control" id="name" name="name" type="text" v-model="name"/> | |
</div> | |
<!– End Your Name Field–> | |
<!– Start phone Field–> | |
<div class="form-group "> | |
<label class="contrl-label " for="phone"> | |
Office Phone | |
</label> | |
<input class="form-control" id="phone" name="phone" type="text" v-model="officePhone"/> | |
</div> | |
<!– End phone Field–> | |
<!– Start location Field–> | |
<div class="form-group "> | |
<label class="control-label " for="location"> | |
Location | |
</label> | |
<input class="form-control" id="location" name="location" type="text" v-model="location"/> | |
</div> | |
<!– End location Field–> | |
<!– Start email Field–> | |
<div class="form-group "> | |
<label class="control-label " for="email"> | |
</label> | |
<input class="form-control" list="siteUerEmails" id="email" name="email" type="text" v-model="email"/> | |
<datalist id="siteUerEmails"> | |
<option v-for="email in siteEmails" v-bind:value="email.Email"></option> | |
</datalist> | |
</div> | |
<!– End email Field–> | |
<!– Start requestType Field–> | |
<div class="form-group "> | |
<label class="control-label " for="requestType"> | |
Request Type | |
</label> | |
<select class="select form-control" id="requestType" name="requestType" v-on:change="showRequestType" v-model="requestType"> | |
<option selected="selected" value=""> | |
</option> | |
<option value="Laptop"> | |
Laptop | |
</option> | |
<option value="Mobile"> | |
Mobile | |
</option> | |
</select> | |
</div> | |
<!– End requestType Field–> | |
<!– Start description Field–> | |
<div class="form-group "> | |
<label class="control-label " for="textarea"> | |
Description | |
</label> | |
<textarea class="form-control" cols="40" id="textarea" name="textarea" rows="10" v-model="description"></textarea> | |
</div> | |
<!– End description Field–> | |
<!– BEGIN TEMPLATE –> | |
<!– BEGIN MOBILE SECTION –> | |
<template v-if="boolMobile"> | |
<!– Start mobilePhone Field–> | |
<div class="form-group "> | |
<label class="control-label " for="mobilePhone"> | |
Mobile #: | |
</label> | |
<input class="form-control" id="mobilePhone" name="mobilePhone" type="text" v-model="mobileNum" /> | |
</div> | |
<!– End mobilePhone Field–> | |
<!– Start phoneBrand Field–> | |
<div class="form-group "> | |
<label class="control-label " for="select1"> | |
Phone brand | |
</label> | |
<select class="select form-control" id="select1" name="select1" v-model="phoneBrand"> | |
<option selected="selected" value=""> | |
</option> | |
<option value="Apple"> | |
Apple | |
</option> | |
<option value="Google"> | |
</option> | |
<option value="Nokia"> | |
Nokia | |
</option> | |
<option value="LG"> | |
LG | |
</option> | |
<option value="Samsung"> | |
Samsung | |
</option> | |
</select> | |
</div> | |
<!– End phoneBrand Field–> | |
<!– Start Mobile Operating System Field–> | |
<div class="form-group "> | |
<label class="control-label "> | |
Mobile Operating System | |
</label> | |
<div class=""> | |
<div class="radio"> | |
<label class="radio"> | |
<input name="radio" type="radio" value="Android" v-model="mobileOS" v-on:click="showHideMobileModel"/> | |
Android | |
</label> | |
</div> | |
<div class="radio"> | |
<label class="radio"> | |
<input name="radio" type="radio" value="iPhone" v-model="mobileOS" v-on:click="showHideMobileModel"/> | |
iPhone | |
</label> | |
</div> | |
</div> | |
</div> | |
<!– End Mobile Operating System Field–> | |
<!– BEGIN ANDROID Model –> | |
<div class="form-group" v-if="boolAndroidModel"> | |
<label class="control-label " for="androidModels"> | |
Android Models | |
</label> | |
<select class="select form-control" id="androidmodels" name="androidmodels" v-model="androidmodels"> | |
<option selected="selected" value=""> | |
</option> | |
<option value="Google Pixel 3"> | |
Google Pixel 3 | |
</option> | |
<option value="Samsung Galaxy"> | |
Samsung Galaxy | |
</option> | |
</select> | |
</div> | |
<!– END ANDROID Model –> | |
<!– BEGIN iPHONE Model –> | |
<div class="form-group " v-if="booliPhoneModel"> | |
<label class="control-label " for="select4"> | |
iPhone Models | |
</label> | |
<select class="select form-control" id="select4" name="select4" v-model="iphonemodels"> | |
<option selected="selected" value=""> | |
</option> | |
<option value="iPhone 7"> | |
iPhone 7 | |
</option> | |
<option value="iPhone 6"> | |
iPhone 6 | |
</option> | |
</select> | |
<!– END iPHONE Model –> | |
</div> | |
</template> | |
<!– END MOBILE SECTION –> | |
<!– END TEMPLATE –> | |
<!– BEGIN TEMPLATE –> | |
<!– BEGIN LAPTOP SECTION –> | |
<template v-if="boolLaptop"> | |
<div class="form-group "> | |
<label class="control-label " for="laptopBrand"> | |
Laptop Brands | |
</label> | |
<select class="select form-control" id="laptopBrand" v-model="laptopBrands">{{laptopBrands}} | |
<option selected="selected" value=""> | |
</option> | |
<option value="Lenovo"> | |
Lenovo | |
</option> | |
<option value="HP"> | |
HP | |
</option> | |
<option value="Microsoft"> | |
Microsoft | |
</option> | |
<option value="Dell"> | |
Dell | |
</option> | |
</select> | |
</div> | |
<div class="form-group "> | |
<label class="control-label "> | |
Laptop OS | |
</label> | |
<div class=""> | |
<div class="radio"> | |
<label class="radio"> | |
<input name="LaptopOS" type="radio" value="Windows 7" v-model="laptopOS" />{{laptopOS}} | |
Windows 7 | |
</label> | |
</div> | |
<div class="radio"> | |
<label class="radio"> | |
<input name="LaptopOS" type="radio" value="Linux" v-model="laptopOS" /> | |
Linux | |
</label> | |
</div> | |
</div> | |
</div> | |
<div class="form-group " v-if="boolLaptopSerial"> | |
<label class="control-label " for="text3"> | |
Laptop Serial # | |
</label> | |
<input class="form-control" id="text3" name="text3" type="text"/> | |
</div> | |
</template> | |
<!– END LAPTOP SECTION –> | |
<!– END TEMPLATE –> | |
<div class="form-group"> | |
<div> | |
<button class="btn btn-primary btn-sm" name="submit" type="button" v-on:click="submitForm"> | |
Submit | |
</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script src="/sites/SharePointSaturdays/SPSaturday/webpart/helpdesk/helpdesk.js"></script> |
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
new Vue({ | |
el:'#app', | |
data: { | |
//test:'Good luck!', | |
errors: [], | |
name:null, description:null, email:null, | |
officePhone:'', location:'', | |
requestType:'', | |
mobileNum:'', | |
phoneBrand:'', | |
mobileOS:'', | |
androidmodels:'', | |
iPhonemodels:'', | |
laptopBrands:'', | |
laptopOS:'', | |
laptopSerial:'', | |
siteEmails: [], | |
laptops:'', | |
boolLaptopSerial:false, | |
boolAndroidModel: false, | |
booliPhoneModel: false, | |
boolMobile:false, | |
boolLaptop:false | |
}, | |
created: function(){ | |
this.getSiteUsers(); | |
}, | |
methods: { | |
showRequestType: function(e) {/* Access event object */ | |
if (e.target.value == 'Laptop'){ | |
this.boolLaptop = true; | |
} else { | |
this.boolLaptop = false; | |
} | |
if (e.target.value == 'Mobile'){ | |
this.boolMobile = true; | |
} else { | |
this.boolMobile = false; | |
} | |
}, | |
showHideMobileModel: function(e){ | |
if (e.target.value == "iPhone"){ | |
this.booliPhoneModel = true; | |
this.boolAndroidModel = false; | |
}else{ | |
this.boolAndroidModel = true; | |
this.booliPhoneModel = false; | |
} | |
}, | |
getSiteUsers: function(){ | |
var siteUrl = _spPageContextInfo.webAbsoluteUrl; | |
var fullUrl = siteUrl + "/_api/web/siteusers?$select=Email"; | |
var headers = { | |
"accept": "application/json;odata=verbose" | |
}; | |
var vm = this; | |
$.ajax({ | |
url: fullUrl, | |
type: "GET", | |
headers: headers, | |
success: function success(data) { | |
console.log(data); | |
vm.siteEmails = data.d.results; | |
} | |
}); | |
}, | |
submitForm: function(){ | |
if (this.validateForm()){ | |
var siteUrl = _spPageContextInfo.webAbsoluteUrl; | |
var fullUrl = siteUrl + "/_api/web/lists/GetByTitle('helpdesk')/items"; | |
$.ajax({ | |
url: fullUrl, | |
method: "POST", | |
data: JSON.stringify({ | |
'__metadata': { 'type': 'SP.Data.HelpdeskListItem' }, | |
'Title': this.name, | |
'OfficePhone': this.officePhone || 'NA', | |
'Location': this.location, | |
'Email': this.email, | |
'RequestType': this.requestType, | |
'Description': this.description, | |
'laptopBrands': this.laptopBrands, | |
'laptopos': this.laptopOS, | |
'MobileNumber': this.mobileNum, | |
'phonebrand': this.phoneBrand, | |
'mobileos': this.mobileOS, | |
'iphonemodels': this.iphonemodels, | |
'androidmodels': this.androidmodels | |
}), | |
headers: { | |
"accept": "application/json;odata=verbose", | |
"content-type": "application/json;odata=verbose", | |
"X-RequestDigest": $("#__REQUESTDIGEST").val() | |
}, | |
success: function(data){ | |
alert("Submit was a success!"); | |
}, | |
error: function(data){ | |
console.log(data); | |
} | |
}); | |
} | |
}, | |
validateForm: function() { | |
this.errors = []; | |
if (!this.name){ | |
this.errors.push("Name required."); | |
} | |
if (!this.description){ | |
this.errors.push('Description required.') | |
} | |
if (!this.email){ | |
this.errors.push('Email required.') | |
}else if(!this.validEmail(this.email)){ | |
this.errors.push('Valid email required.'); | |
} | |
if (!this.errors.length){ | |
return true; | |
} | |
console.log(this.errors); | |
}, | |
validEmail: function (email) { | |
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; | |
return re.test(email); | |
} | |
} | |
}) |