validate data using map function - vue.js

I would like to validate data using map.I would like to get the key name and check some conditions
const obj = {
firstName: ['errorFirstName', 'msgFirstName'],
lastName: ['errorLastName', 'msgLastName'],
middleName: ['errorMiddleName', 'msgMiddleName'],
}
if (Object.keys(obj).includes(field)) {
//I would like to pass here the object key length for each key :example if(this.firstName.length === 0)
if(this[obj[key]].length === 0) {
const [hasError, msg] = obj[field];
this[hasError] = true;
this[msg] = `${field} is required.`;
}
}

Simply use the key field to retrieve the value from your object:
const obj = {
firstName: ['errorFirstName', 'msgFirstName'],
lastName: ['errorLastName', 'msgLastName'],
middleName: ['errorMiddleName', 'msgMiddleName'],
}
Object.keys(obj).forEach(fieldName => {
if (this[fieldName].length === 0) {
// your logic here
const [hasError, msg] = obj[fieldName];
this[hasError] = true;
this[msg] = `${fieldName} is required.`;
}
}

Related

How can I seperate functions which are basically the same but use different states? Vue2/Vuex

Ive got a problem since i realized that I break the DRY(Dont repeat yourself) rule. So basically I have 2 modules(movies, cinemas) and few methods in them which look the same but use their module' state.
Example: Movies has 'movies' state. Cinemas has 'cinemas' state.
//cinemas.ts
#Mutation
deleteCinemaFromStore(id: string): void {
const cinemaIndex = this.cinemas.findIndex((item) => item.id === id);
if (cinemaIndex >= 0) {
const cinemasCopy = this.cinemas.map((obj) => {
return { ...obj };
});
cinemasCopy.splice(cinemaIndex, 1);
this.cinemas = cinemasCopy;
} else {
throw new Error("Provided id doesn't exist");
}
}
//movies.ts
#Mutation
deleteMovieFromStore(id: string): void {
const movieIndex = this.movies.findIndex((item) => item.id === id);
if (movieIndex >= 0) {
const moviesCopy = this.movies.map((obj) => {
return { ...obj };
});
moviesCopy.splice(movieIndex, 1);
this.movies = moviesCopy;
} else {
throw new Error("Provided id doesn't exist");
}
}
My struggle is: How can I seperate these methods into utils.ts if they have reference to 2 different states?
define another function that take the id, state and store context (this) as parameters :
function delete(id:string,itemsName:string,self:any){
const itemIndex= self[itemsName].findIndex((item) => item.id === id);
if (itemIndex>= 0) {
const itemsCopy = self[itemsName].map((obj) => {
return { ...obj };
});
itemsCopy.splice(itemIndex, 1);
self[itemsName] = itemsCopy;
} else {
throw new Error("Provided id doesn't exist");
}
}
then use it like :
//cities.ts
#Mutation
deleteCityFromStore(id: string): void {
delete(id,'cities',this)
}
//countries.ts
#Mutation
deleteCountryFromStore(id: string): void {
delete(id,'countries',this)
}

Wrong queryString when building navigation plan in aurelia-router

We're using aurelia-open-id-connect in our project and after successful login the redirect is removing the querystring from the url. I've debugged my way through the aurelia-router and I think I found something. Should'nt the queryString in redirectInstruction be used there?
export const buildRedirectPlan = (instruction: NavigationInstruction) => {
const config = instruction.config;
const router = instruction.router;
return router
._createNavigationInstruction(config.redirect)
.then(redirectInstruction => {
const params: Record<string, any> = {};
const originalInstructionParams = instruction.params;
const redirectInstructionParams = redirectInstruction.params;
for (let key in redirectInstructionParams) {
// If the param on the redirect points to another param, e.g. { route: first/:this, redirect: second/:this }
let val = redirectInstructionParams[key];
if (typeof val === 'string' && val[0] === ':') {
val = val.slice(1);
// And if that param is found on the original instruction then use it
if (val in originalInstructionParams) {
params[key] = originalInstructionParams[val];
}
} else {
params[key] = redirectInstructionParams[key];
}
}
let redirectLocation = router.generate(redirectInstruction.config, params, instruction.options);
// Special handling for child routes
for (let key in originalInstructionParams) {
redirectLocation = redirectLocation.replace(`:${key}`, originalInstructionParams[key]);
}
let queryString = instruction.queryString;
// use redirectInstruction.queryString instead?
if (queryString) {
redirectLocation += '?' + queryString;
}
return Promise.resolve(new Redirect(redirectLocation));
});
};

React Native SectionList (title, data) - Search in the data field

I am trying to build Search function in SectionList. I have search inside the 'data' (second field) and not inside 'title' but I am not able to make it work.
My Data is about the Flat / resident details of an Apartment -
sectiondata =
[{"title":"GROUND FLOOR",
"data":[
{"id":"48","res_type":"owner","user_name":"Ashwani","flat_id":"1","flat_name":"001","floor_no":"GROUND FLOOR","floor_int":"0","signal_player_id":"aa","user_phone":"98855550"},
{"id":"49","res_type":"owner","user_name":"Rahul","flat_id":"2","flat_name":"002","floor_no":"GROUND FLOOR","floor_int":"0","signal_player_id":"aa","user_phone":"999999"}
]
}]
I am trying something like this but it is not working.
searchFilterFunction = (text) => {
let search = text.toLowerCase();
this.setState({
check: this.state.sectiondata.filter(
obj => obj.data['flat_name'].toLowerCase().includes(search))
});
}
How to filter data base on name? Please assist here.
Thanks.
You can try to search like this:
onChangeText(text) {
if (text.trim().length > 0) {
var temp = []
sectiondata.map((item) => {
var dataItem = {};
var brandData = [];
item.data.map((searchItem) => {
let flatName = searchItem.flat_name
if (flatName.match(text)) {
brandData.push(searchItem);
}
})
if (brandData.length > 0) {
} else {
return null;
}
dataItem.brandData = brandData;
temp.push(dataItem);
this.setState({
sectiondata: temp
})
})
} else {
this.setState({
sectiondata: this.state.tempData
})
}
}
searchFilterFunction(text) {
if( text == undefined || text == '') {
this.setState({
sectiondata: this.arrayholder
})
return;
}
if (text.trim().length > 0) {
var temp = []
this.state.sectiondata.map((item) => {
var dataItem = {};
var title = item.title;
var brandData = [];
item.data.map((searchItem) => {
let flatName = searchItem.flat_name
if (flatName.match(text)) {
brandData.push(searchItem);
}
})
if (brandData.length > 0) {
} else {
return null;
}
dataItem.title = title;
dataItem.data = brandData;
temp.push(dataItem);
this.setState({
sectiondata: temp
})
})

Aurelia - property that is 2-way bound on custom template and populates form always shows undefined in console

I have a two way bound object in a custom element. Its two way bound to the parent.
The parent, client.ts, does a fetch for the client data based on a clientDetails class.
The child here is the Address custom element.
When the client form is populated with a client so is the address component via the bind.
In the address.ts (child here) I have initialized the two way bind as so:
#bindable({ defaultBindingMode: bindingMode.twoWay }) address = new AddressDetails;
AddressDetails is as follows:
import { Serializable } from "../../../../services/serializable/Serializable"
import { AddressLocation } from "./addressLocation"
export class AddressDetails implements Serializable<AddressDetails> {
address1: string;
address2: string;
addressLocation: AddressLocation;
deserialize(input) {
//console.log("INPUT: ", input)
this.address1 = input.address1;
this.address2 = input.address2;
if (input.addressLocation) {
this.addressLocation = new AddressLocation;
this.addressLocation.deserialize(input.addressLocation);
}
return this;
}
}
When a client is requested for edit it all works so if a client is populated then so is the address component.
My problem is that I am getting errors wherever I try and set a value thats part of the bind object. that is, If I want to set the stateShortName as per:
this.address.addressLocation.stateShortName = this.companyStateShortName;
I get the error:
address.ts:72 Uncaught (in promise) TypeError: Cannot set property 'stateShortName' of undefined
As it states this.address.addressLocation.stateShortName is undefined.
This caused me to check if I could console.log the value of this.address in a "created" function as well as "bind" and "attached".
So even though I have bound this object, initialized at the start as AddressDetails it always comes up as undefined even when all the fields show values it still errors as "undefined".
Even though I have initialized this object from the start no matter where I try and access this two way bound object I cant because its "undefined"
Why cant I access it??
..and how do I access "this.address" or any of its members so I can, say, set one of the object's members to a value??
Below is the whole class for the "address.ts" for context. I get an error any time I try and access or set this.address in this class.
import { HttpClient } from "aurelia-fetch-client";
import { bindable, bindingMode, autoinject, inject, NewInstance, PLATFORM } from "aurelia-framework";
import { Router, activationStrategy } from "aurelia-router";
import {
ValidationControllerFactory,
ValidationController,
ValidationRules
} from "aurelia-validation";
import { BootstrapFormRenderer } from "../../../../services/bootstrapFormRenderer/bootstrapFormRenderer";
import { AuthService } from "../../../../services/auth/auth-service"
import { AddressDetails } from "../address/addressDetails"
import { AddressLocation } from "./addressLocation"
#autoinject
export class Address {
#bindable({ defaultBindingMode: bindingMode.twoWay }) address = new AddressDetails;
postcode: string;
states = Array();
companyStateShortName: string;
constructor(
private authService: AuthService) {
this.getStateData();
}
created(owningView, myView) {
console.log("CONSTRUCTOR ADDRESS: ", typeof this.address, this.address);
}
bind(bindingContext, overrideContext) {
if (this.address.addressLocation.postcode === "undefined") {//we want it to match
setTimeout(50);//wait 50 millisecnds then recheck
return;
}
console.log("BIND ADDRESS: ", this.address);
}
attached() {
console.log("ATTACHED ADDRESS: ", this.address);
}
// Single fetch for poplulating the states and obtaining the default state.
getStateData() {
const headers = this.authService.header();
let stateDropdown = fetch("/api/selectData/GetStatesAndCompanyStateId", {
method: "GET",
headers
})
.then(response => response.json())
.then(data => {
for (const key in data.stateDropDownList) {
this.states[key] = data.stateDropDownList[key].stateShortName;
}
console.log("ADDRESS get state data: ", this.address);
console.log("data: ", data)
this.companyStateShortName = data.companyStateShortName;
console.log("StateShortName: ", this.companyStateShortName)
})
.then(() => {
//if (typeof this.address.addressLocation != "undefined") {
//this.address = new AddressDetails;
//this.address.addressLocation = new AddressLocation;
//debugger;
console.log("this.address.addressLocation: ", typeof this.address, this.address)
this.address.addressLocation.stateShortName = this.companyStateShortName;
//}
});
return stateDropdown;
}
// Fetch for async suburb dropdown.
async getSuburbData(filter: string, limit: number) {
const headers = this.authService.header();
if (this.address) {
}
else {
console.log('undefined')
}
const queryStringValues = {
query: filter,
stateShortName: this.companyStateShortName
};
const queryString = "?" + Object.keys(queryStringValues)
.filter(key => typeof queryStringValues[key] !== "undefined" && queryStringValues[key] !== null)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(queryStringValues[key])}`)
.join("&");
console.log("queryStringValue; ", queryString)
//console.log("initial suburb", this.address.addressLocation.suburb);
let suburbLookup = await fetch("/api/selectData/QuerySuburbs" + queryString, {
method: "GET",
headers: headers
})
.then(response => {
return response.json();
})
.then(addressLocation => filter.length > 0 ? addressLocation.filter(item => item.suburb.toLowerCase().indexOf(filter.toLowerCase()) > -1) : addressLocation)
.then(addressLocation => limit ? addressLocation.splice(0, limit) : addressLocation); // Not really needed - its done on the server.
//.then(suburbs => console.log("Suburbs: ", suburbs));
//this.postCode = this.address.postcode;
console.log("suburbLookup", suburbLookup);
return suburbLookup
}
suburbSelected(item) {
//debugger;
//console.log("BEFORE ASSIGNMENT OF SUBURB NAME: ", item, item.postcode, this.address.addressLocation.postcode)
if (this.address.addressLocation != null && item != null) {
console.log("2 changed suburb", this.address.addressLocation.suburb);
//this.address.addressLocation.suburb = item.name
var test = item.postcode;
//this.address.addressLocation.postcode = item.postcode;
//this.address.addressLocation.addressLocationId = item.addressLocationId;
} else {
// this.address.addressLocation.postcode = "-";
}
console.log("AFTER ASSIGNMENT OF SUBURB NAME: ", item, this.address)
}
}
class StateDropdownAndCompanyState {
companyStateShortName: string;
stateDropdownList: StateDropdown[];
}
class StateDropdown {
stateId: number;
stateShortName: string;
stateName: string;
stateLabel: string;
}
class suburbQuery {
query: string;
stateShortName: string;
}

Trello API add base64 data image as an attachement

I'd like to send base64 image as an attachment to a trello card through the API
POST /1/cards/[card id or shortlink]/attachments
There's a file field but it does not specify how should look the data there.
Refs: https://developers.trello.com/advanced-reference/card#post-1-cards-card-id-or-shortlink-attachments
Any idea?
Short answer: Trello's API only works to attach binary data via multipart/form-data. Examples below.
Long answer:
The Trello API to add attachments and images is frustratingly under-documented. They do have a coffeescript Client.js for those of us using Javascript to simplify all the basic operations: https://trello.com/1/client.coffee
Using the vanilla Client.js file I have been able to attach links and text files. While the CURL example shows pulling a binary file in from a hard drive, that doesn't work for those of us completely on a server or client where we don't have permissions to create a file.
From a LOT of trial and error, I've determined all binary data (images, documents, etc.) must be attached using multipart/form-data. Here is a jQuery snippet that will take a URL to an item, get it into memory, and then send it to Trello.
var opts = {'key': 'YOUR TRELLO KEY', 'token': 'YOUR TRELLO TOKEN'};
var xhr = new XMLHttpRequest();
xhr.open('get', params); // params is a URL to a file to grab
xhr.responseType = 'blob'; // Use blob to get the file's mimetype
xhr.onload = function() {
var fileReader = new FileReader();
fileReader.onload = function() {
var filename = (params.split('/').pop().split('#')[0].split('?')[0]) || params || '?'; // Removes # or ? after filename
var file = new File([this.result], filename);
var form = new FormData(); // this is the formdata Trello needs
form.append("file", file);
$.each(['key', 'token'], function(iter, item) {
form.append(item, opts.data[item] || 'ERROR! Missing "' + item + '"');
});
$.extend(opts, {
method: "POST",
data: form,
cache: false,
contentType: false,
processData: false
});
return $.ajax(opts);
};
fileReader.readAsArrayBuffer(xhr.response); // Use filereader on blob to get content
};
xhr.send();
I have submitted a new coffeescript for Trello developer support to consider uploading to replace Client.js. It adds a "Trello.upload(url)" that does this work.
I've also attached here for convenience in JS form.
// Generated by CoffeeScript 1.12.4
(function() {
var opts={"version":1,"apiEndpoint":"https://api.trello.com","authEndpoint":"https://trello.com"};
var deferred, isFunction, isReady, ready, waitUntil, wrapper,
slice = [].slice;
wrapper = function(window, jQuery, opts) {
var $, Trello, apiEndpoint, authEndpoint, authorizeURL, baseURL, collection, fn, fn1, i, intentEndpoint, j, key, len, len1, localStorage, location, parseRestArgs, readStorage, ref, ref1, storagePrefix, token, type, version, writeStorage;
$ = jQuery;
key = opts.key, token = opts.token, apiEndpoint = opts.apiEndpoint, authEndpoint = opts.authEndpoint, intentEndpoint = opts.intentEndpoint, version = opts.version;
baseURL = apiEndpoint + "/" + version + "/";
location = window.location;
Trello = {
version: function() {
return version;
},
key: function() {
return key;
},
setKey: function(newKey) {
key = newKey;
},
token: function() {
return token;
},
setToken: function(newToken) {
token = newToken;
},
rest: function() {
var args, error, method, params, path, ref, success;
method = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
ref = parseRestArgs(args), path = ref[0], params = ref[1], success = ref[2], error = ref[3];
opts = {
url: "" + baseURL + path,
type: method,
data: {},
dataType: "json",
success: success,
error: error
};
if (!$.support.cors) {
opts.dataType = "jsonp";
if (method !== "GET") {
opts.type = "GET";
$.extend(opts.data, {
_method: method
});
}
}
if (key) {
opts.data.key = key;
}
if (token) {
opts.data.token = token;
}
if (params != null) {
$.extend(opts.data, params);
}
if (method === 'UPLOAD' && typeof (params) === "string" && params.length > 5) {
var xhr = new XMLHttpRequest();
xhr.open('get', params);
xhr.responseType = 'blob'; // Use blob to get the mimetype
xhr.onload = function() {
var fileReader = new FileReader();
fileReader.onload = function() {
var filename = (params.split('/').pop().split('#')[0].split('?')[0]) || params || '?'; // Removes # or ? after filename
var file = new File([this.result], filename);
var form = new FormData();
form.append("file", file);
$.each(['key', 'token'], function(iter, item) {
form.append(item, opts.data[item] || 'ERROR! Missing "' + item + '"');
});
$.extend(opts, {
method: "POST",
data: form,
cache: false,
contentType: false,
processData: false
});
return $.ajax(opts);
};
fileReader.readAsArrayBuffer(xhr.response); // Use filereader on blob to get content
};
xhr.send();
} else {
return $.ajax(opts);
}
},
authorized: function() {
return token != null;
},
deauthorize: function() {
token = null;
writeStorage("token", token);
},
authorize: function(userOpts) {
var k, persistToken, ref, regexToken, scope, v;
opts = $.extend(true, {
type: "redirect",
persist: true,
interactive: true,
scope: {
read: true,
write: false,
account: false
},
expiration: "30days"
}, userOpts);
regexToken = /[&#]?token=([0-9a-f]{64})/;
persistToken = function() {
if (opts.persist && (token != null)) {
return writeStorage("token", token);
}
};
if (opts.persist) {
if (token == null) {
token = readStorage("token");
}
}
if (token == null) {
token = (ref = regexToken.exec(location.hash)) != null ? ref[1] : void 0;
}
if (this.authorized()) {
persistToken();
location.hash = location.hash.replace(regexToken, "");
return typeof opts.success === "function" ? opts.success() : void 0;
}
if (!opts.interactive) {
return typeof opts.error === "function" ? opts.error() : void 0;
}
scope = ((function() {
var ref1, results;
ref1 = opts.scope;
results = [];
for (k in ref1) {
v = ref1[k];
if (v) {
results.push(k);
}
}
return results;
})()).join(",");
switch (opts.type) {
case "popup":
(function() {
var authWindow, height, left, origin, receiveMessage, ref1, top, width;
waitUntil("authorized", (function(_this) {
return function(isAuthorized) {
if (isAuthorized) {
persistToken();
return typeof opts.success === "function" ? opts.success() : void 0;
} else {
return typeof opts.error === "function" ? opts.error() : void 0;
}
};
})(this));
width = 420;
height = 470;
left = window.screenX + (window.innerWidth - width) / 2;
top = window.screenY + (window.innerHeight - height) / 2;
origin = (ref1 = /^[a-z]+:\/\/[^\/]*/.exec(location)) != null ? ref1[0] : void 0;
authWindow = window.open(authorizeURL({
return_url: origin,
callback_method: "postMessage",
scope: scope,
expiration: opts.expiration,
name: opts.name
}), "trello", "width=" + width + ",height=" + height + ",left=" + left + ",top=" + top);
receiveMessage = function(event) {
var ref2;
if (event.origin !== authEndpoint || event.source !== authWindow) {
return;
}
if ((ref2 = event.source) != null) {
ref2.close();
}
if ((event.data != null) && /[0-9a-f]{64}/.test(event.data)) {
token = event.data;
} else {
token = null;
}
if (typeof window.removeEventListener === "function") {
window.removeEventListener("message", receiveMessage, false);
}
isReady("authorized", Trello.authorized());
};
return typeof window.addEventListener === "function" ? window.addEventListener("message", receiveMessage, false) : void 0;
})();
break;
default:
window.location = authorizeURL({
redirect_uri: location.href,
callback_method: "fragment",
scope: scope,
expiration: opts.expiration,
name: opts.name
});
}
},
addCard: function(options, next) {
var baseArgs, getCard;
baseArgs = {
mode: 'popup',
source: key || window.location.host
};
getCard = function(callback) {
var height, left, returnUrl, top, width;
returnUrl = function(e) {
var data;
window.removeEventListener('message', returnUrl);
try {
data = JSON.parse(e.data);
if (data.success) {
return callback(null, data.card);
} else {
return callback(new Error(data.error));
}
} catch (error1) {}
};
if (typeof window.addEventListener === "function") {
window.addEventListener('message', returnUrl, false);
}
width = 500;
height = 600;
left = window.screenX + (window.outerWidth - width) / 2;
top = window.screenY + (window.outerHeight - height) / 2;
return window.open(intentEndpoint + "/add-card?" + $.param($.extend(baseArgs, options)), "trello", "width=" + width + ",height=" + height + ",left=" + left + ",top=" + top);
};
if (next != null) {
return getCard(next);
} else if (window.Promise) {
return new Promise(function(resolve, reject) {
return getCard(function(err, card) {
if (err) {
return reject(err);
} else {
return resolve(card);
}
});
});
} else {
return getCard(function() {});
}
}
};
ref = ["GET", "PUT", "POST", "DELETE", "UPLOAD"];
fn = function(type) {
return Trello[type.toLowerCase()] = function() {
return this.rest.apply(this, [type].concat(slice.call(arguments)));
};
};
for (i = 0, len = ref.length; i < len; i++) {
type = ref[i];
fn(type);
}
Trello.del = Trello["delete"];
ref1 = ["actions", "cards", "checklists", "boards", "lists", "members", "organizations", "lists"];
fn1 = function(collection) {
return Trello[collection] = {
get: function(id, params, success, error) {
return Trello.get(collection + "/" + id, params, success, error);
}
};
};
for (j = 0, len1 = ref1.length; j < len1; j++) {
collection = ref1[j];
fn1(collection);
}
window.Trello = Trello;
authorizeURL = function(args) {
var baseArgs;
baseArgs = {
response_type: "token",
key: key
};
return authEndpoint + "/" + version + "/authorize?" + $.param($.extend(baseArgs, args));
};
parseRestArgs = function(arg) {
var error, params, path, success;
path = arg[0], params = arg[1], success = arg[2], error = arg[3];
if (isFunction(params)) {
error = success;
success = params;
params = {};
}
path = path.replace(/^\/*/, "");
return [path, params, success, error];
};
localStorage = window.localStorage;
if (localStorage != null) {
storagePrefix = "trello_";
readStorage = function(key) {
return localStorage[storagePrefix + key];
};
writeStorage = function(key, value) {
if (value === null) {
return delete localStorage[storagePrefix + key];
} else {
return localStorage[storagePrefix + key] = value;
}
};
} else {
readStorage = writeStorage = function() {};
}
};
deferred = {};
ready = {};
waitUntil = function(name, fx) {
if (ready[name] != null) {
return fx(ready[name]);
} else {
return (deferred[name] != null ? deferred[name] : deferred[name] = []).push(fx);
}
};
isReady = function(name, value) {
var fx, fxs, i, len;
ready[name] = value;
if (deferred[name]) {
fxs = deferred[name];
delete deferred[name];
for (i = 0, len = fxs.length; i < len; i++) {
fx = fxs[i];
fx(value);
}
}
};
isFunction = function(val) {
return typeof val === "function";
};
wrapper(window, jQuery, opts);
}).call(this);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>