I am trying to set custom validity for a date field, that throws an error message when I select any day which is not Sunday in Lightning Web Component - salesforce-lightning

This is my lightning input for date, which has a onchange event dateHandleChange. This is my first lwc.
te.html
<div class=" slds-size_1-of-4 ">
<lightning-input type="date" label="Pick a Sunday" name="date" value={dateEntry} onchange={dateHandleChange} required></lightning-input>
</div>
This is the js file which handles the onchange event, please can someone help.
te.js
dateHandleChange(event){
let errorMessage = 'Please enter a Sunday.';
let fieldSel = this.template.querySelector(".date");
this.dateEntry = event.target.value;
let val = this.dateEntry.getDate();
if(val == '0'){
fieldSel.setCustomValidity('');
} else {
fieldSel.setCustomValidity(errorMessage);
}
fieldSel.reportValidity();
}

Related

How do I rename files uploaded to an apps script web app form?

I've made a little web app form by splicing together some code I found. It works nearly perfectly for me, allowing me to upload files to a Google Drive folder, logging the data submitted in the form in a spreadsheet and emailing me when a file is uploaded.
However, what I really want to be able to do is to rename the files that are uploaded according to the form data. For example, if the inputted manufacturer value = "Sony" and the date value = 12-04-2016, then make the filename "Sony_12-04-2016.pdf"
From looking it up as best I can it seems I need to pass the submitted values into the createFile() function but I'm quite new to coding and not really sure what I'm doing here..
Here's what I have so far:
.gs
var TO_ADDRESS = "my email address";
function doGet(e) {
return HtmlService.createTemplateFromFile('index')
.evaluate()
.setTitle('Price List Upload Form')
}
function processForm(theForm) {
var fileBlob = theForm.fileUpload;
Logger.log("fileBlob Name: " + fileBlob.getName())
Logger.log("fileBlob type: " + fileBlob.getContentType())
Logger.log('fileBlob: ' + fileBlob);
var fldrSssn = DriveApp.getFolderById('my Google Drive folder id');
fldrSssn.createFile(fileBlob);
return true;
}
function formatMailBody(obj) {
var result = "";
for (var key in obj) {
result += "<h4 style='text-transform: capitalize; margin-bottom: 0'>" + key + "</h4><div>" + obj[key] + "</div>";
}
return result;
}
function doPost(e) {
try {
Logger.log(e);
record_data(e);
var mailData = e.parameters;
MailApp.sendEmail({
to: TO_ADDRESS,
subject: "New Price List Uploaded",
htmlBody: formatMailBody(mailData)
});
return ContentService
.createTextOutput(
JSON.stringify({"result":"success",
"data": JSON.stringify(e.parameters) }))
.setMimeType(ContentService.MimeType.JSON);
} catch(error) {
Logger.log(error);
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": e}))
.setMimeType(ContentService.MimeType.JSON);
}
}
function record_data(e) {
Logger.log(JSON.stringify(e));
try {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var sheet = doc.getSheetByName('responses');
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
var nextRow = sheet.getLastRow()+1;
var row = [ new Date() ];
for (var i = 1; i < headers.length; i++) {
if(headers[i].length > 0) {
row.push(e.parameter[headers[i]]);
}
}
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
}
catch(error) {
Logger.log(e);
}
finally {
return;
}
}
.html
<form id="gform" autocomplete="on" method="POST" class="pure-form pure-form-stacked"
action="script url" onsubmit="picUploadJs(this)">
<fieldset class="pure-group">
<input name="fileUpload" type="file" />
</fieldset>
<fieldset class="pure-group">
<label for="manufacturer">Manufacturer: </label>
<input id="manufacturer" name="manufacturer" type="text" placeholder="Manufacturer Name" required/>
</fieldset>
<fieldset class="pure-group">
<label for="issueDate">Date Issued: </label>
<input id="issueDate" name="issueDate" type="date" required />
</fieldset>
<fieldset class="pure-group">
<label for="info">Additional Info: </label>
<input id="info" name="info" type="text" placeholder="Any Additional Information"/>
</fieldset>
<fieldset class="pure-group">
<input id="email" name="email" type="hidden" value="test#gmail.com"/>
</fieldset>
<button class="button-success pure-button button-xlarge">
Upload</button>
<div style="display:none;" id="thankyou_message">
<div id="status" style="display: none">
<h2>Uploading. Please wait...</h2>
</div>
</div>
function picUploadJs(frmData) {
document.getElementById('status').style.display = 'inline';
google.script.run
.withSuccessHandler(updateOutput)
.processForm(frmData)
};
function updateOutput() {
var outputDiv = document.getElementById('status');
outputDiv.innerHTML = "<h2>File successfully uploaded!</h2><button class=\"pure-button\">Upload another</button>";
}
The original code comes from here
and here
I probably don't have all the lingo correct, but you have to turn the form submission fields into variables to be able to use them in your .gs script. Once you turn them into variables, you can "build" a filename to your liking, and use it when writing the fileBlob to a file. Given your code above, you should be able to just modify the processForm function as follows:
function processForm(theForm) {
var fileBlob = theForm.fileUpload;
var manufacturer = theForm.manufacturer;
var issueDate = theForm.issueDate;
var myNewFilename = manufacturer + '_' + issueDate + '.pdf';
fileBlob.setName(myNewFilename); //set Name of the blob
var fldrSssn = DriveApp.getFolderById('my Google Drive folder id');
fldrSssn.createFile(fileBlob); // create a file with the blob, name of the file will be the same as set by setName method
return true;
}
Let me also note something that may be helpful for future visitors--how to write a timestamp into the filename. Set a new variable using the Utilities.formatDate function, and then you can concatenate this variable into a filename like in the example above. Here's how to set the variable:
var myTS = Utilities.formatDate (new Date(), Session.getScriptTimeZone(), "yyyyMMdd_HHmmss--") ;
Format is completely flexible--just look up the function for details.
You may want to use the rename(newName) method which renames the document.
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.rename("This is the new name");
Also, here's a related threads: https://productforums.google.com/forum/#!topic/docs/AP9zMPOyjfg and Copy, rename and move a document which might help.

How to check ion-checkbox from database

I have this ionic tag already populated and with all items unchecked:
<ion-checkbox ng-repeat="categoria in listaCategorias"
ng-model="categoria.checked"
ng-checked="categoria.checked"
ng-change="recuperarServicos(categoria)">
{{ categoria.nmCategoria }}
</ion-checkbox>
And here my controller code that has a list of 'categoria ids':
//here I have the ids recovered from database that I split into an array of ids
var idsCategoria = $scope.meuanuncio.idsCategoria.trim().split(',');
if($scope.listaCategorias.length > 0)
{
//for each item in my listaCategorias (used in ng-repeat)
for (var i = 0; i < $scope.listaCategorias.length; i++) {
var item = $scope.listaCategorias[i];
//I compare id from each item with my list recovered from database
if(idsCategoria.indexOf($scope.listaCategorias[i].idCategoria) != -1)
{
//If the item id exist in database list, I check the item
item.checked = true;
// Below there are other ways that I tried to use
// $scope.listaCategorias[i].Selected = true;
// $scope.listaCategorias[i].checked = true;
$scope.listaCategorias[0].checked = true;
}
}
};
But I can´t do my ion-checkbox item checked.
What am I doing wrong ?
Thanks.
ng-model="categoria.checked"
looks fine, don't think you need the ng-checked though.
var item = $scope.listaCategorias[i];
item.checked = true;
Nope, the item gets lost through the loop. I see you were trying with:
$scope.listaCategorias[i].checked = true;
Did you get an error or something? Because this looks like the way to do it.
Maybe try looping on a div around the ion-checkbox? aka
<div ng-repeat="categoria in listaCategorias">
<ion-checkbox ng-model="categoria.checked"
ng-change="recuperarServicos(categoria)">
{{ categoria.nmCategoria }}
</ion-checkbox>
</div>
try this :
<div ng-repeat="categoria in listaCategorias track by $index">
<ion-item class="item item-checkbox">
<label class="checkbox">
<input type="checkbox" ng-model="categoria.checked" ng-change="recuperarServicos(categoria)">
</label>
{{categoria.nmCategoria}}
</ion-item>
</div>
Controller:
$scope.recuperarServicos = function(categoria){
if(categoria.selected && ($scope.selectedItems.indexOf(categoria.name) < 0)){
$scope.selectedItems.push(categoria.name);
}else{
$scope.selectedItems.splice($scope.selectedItems.indexOf(categoria.name), 1);
}
};
hope this helps you..in someway..!
My problem was when I attribute my array of items to the $scope.listaCategorias.
I was doing that:
$scope.listaCategorias = listaCategorias;
But I need to do that:
$scope.listaCategorias.push.apply($scope.listaCategorias, listaCategorias);
I was building an array with the checked attribute inside, but when I associate my built list, I was associating the first one, which has not the checked attribute setted.
Let me show my code now.
My view :
<div ng-repeat="item in listaCategorias track by $index">
<ion-item class="item item-checkbox">
<label class="checkbox">
<input type="checkbox" ng-model="item.checked" ng-checked="item.checked" ng-change="recuperarServicos(item)">
</label>
{{ item.nmCategoria }}
</ion-item>
</div>
My controller:
//here I get all my 'categorias' from datatable
listaCategorias = appFactory.recuperarCategorias();
//If list is not null go ahead
if(listaCategorias != null) {
//split into an array all my 'categoria' ids
var idsCategoria = $scope.meuanuncio.idsCategoria.split(',');
//if list has items go ahead
if(listaCategorias.length > 0) {
for (var i = 0; i < listaCategorias.length; i++) {
//if 'categoria' id exists in datatable list set true, else false
if(idsCategoria.indexOf(listaCategorias[i].idCategoria) != -1) {
listaCategorias[i].checked = true;
}
else {
listaCategorias[i].checked = false;
}
}
};
//Here is the point !!! I need to load my $scope variable this way to build all my items correctly
$scope.listaCategorias.push.apply($scope.listaCategorias, listaCategorias);
}

How implementing a directive to validate another field (custom form in angularjs)

I have a validation custom form, I use validate-message-character="{{compose.limitCharacter - compose.message.length}}" in a select and textarea like this
<form class="form-horizontal" role="form" name="composeForm" >
<select ng-change="limitComposeCharacter()" ng-selected="compose.profile"
ng-model="compose.profile" ng-options="userId in profiles" name="profile"
validate-message-character="{{compose.limitCharacter - compose.message.length}}" required>
</select>
number Character: {{compose.limitCharacter - compose.message.length}}
<textarea class="form-control" ng-model="compose.message" name="message"
validate-message-character="{{compose.limitCharacter - compose.message.length}}"
required></textarea>
Form validity: {{composeForm.$valid}}
I have something like this:
1° Select User has compose.limitCharacter = 100
2° Select User has compose.limitCharacter = 200 etc etc.
This is my directive to check number Character is > 0
angular.module('App')
.directive('validateMessageCharacter', function () {
return {
require: 'ngModel',
link: function postLink(scope, element, attrs, c) {
scope.$watch(attrs.ngModel, function() {
console.log(attrs.validateMessageCharacter);
if(attrs.validateMessageCharacter < 0)
{
c.$setValidity('maxCharacter', false);
c.$invalid = true;
}else{
c.$setValidity('maxCharacter', true);
c.$invalid = false;
}
});
}
};
});
It doesn't work proply when change select without change the textarea
some advice?
First, using an advice from the angular google group, I changed the scope.$watch to attr.$observe.
Second, the reason it validated only after typing text is that the text area is a required field.
Your code works here:
http://plnkr.co/edit/YvsuLoHzX9eqb7FhDgXA?p=preview

Knockout event binding for input keypress causes weird behavior

Long story short, I want to enable users to hit enter on an input element and certain method in my viewmodel be called. Here is my html input:
<input id="searchBox" class="input-xxlarge" type="text" data-bind="value: searchText, valueUpdate: 'afterkeydown', event: { keypress: $parent.searchKeyboardCmd}">
and here is my method in vm:
searchKeyboardCmd = function (data, event) { if (event.keyCode == 13) searchCmd(); };
everything works fine and searchCmd is called when I hit enter on input, but the problem is that I can type nothing in input, i.e. everything I type into input is ignored. Thank you in advance for your help.
According to KO docs you have to return true from your event handler if you want the default action proceed.
searchKeyboardCmd = function (data, event) {
if (event.keyCode == 13) searchCmd();
return true;
};
here's a fiddle which demonstrates what ur trying to do and also replace event 'keypress' in ur code with keyup and remove $parent with only the function name unless the textfield is inside a knockout foreach loop..here is the below modified code
<input id="searchBox" class="input-xxlarge" type="text" data-bind="value: searchText, valueUpdate: 'afterkeydown', event: { keyup: searchKeyboardCmd}"
Here is a working sample.
http://jsfiddle.net/tlarson/qG6yv/
<!-- ko with: stuff -->
<input id="searchBox" class="input-xxlarge" type="text"
data-bind="value: searchText, valueUpdate: 'afterkeydown',
event: { keypress: $parent.searchKeyboardCmd}">
<!-- /ko -->
And the javascript:
var stuffvm = function(){
var self = this;
self.searchText = ko.observable();
};
var vm = function() {
var self = this;
self.stuff = new stuffvm();
self.searchCmd = function() {
console.log("search triggered");
};
self.searchKeyboardCmd = function (data, event) {
if (event.keyCode == 13) {
self.searchCmd();
}
return true;
}
}
ko.applyBindings(new vm());

Incrementing value (integer) in an input type field

I have input text and I want to increase the number that is inside using the key up or down.
I have:
<input type="text" value="1" name="qty" />
After digging stackoverflow I found: Is it possible to handle up/down key in HTML input field?
The solution is to use: Keycodes 37 - 40 should do it for you. They map as 37=left, 38=up, 39=right, 40=down.
But How can I use these code in my form? Is there a Javascript function that do this (like : increase() or decrease()?
Thanks
You could do something like this, using the "onkeydown" event.
<script type="text/javascript">
function increment(e,field) {
var keynum
if(window.event) {// IE
keynum = e.keyCode
} else if(e.which) {// Netscape/Firefox/Opera
keynum = e.which
}
if (keynum == 38) {
field.value = parseInt(field.value)+ 1;
} else if (keynum == 40) {
field.value = parseInt(field.value) - 1;
}
return false;
}
</script>
<input type="text" onkeydown="increment(event, this)" value="10">