Angular 6 : Validators.pattern not working properly - angular6

I have a Validators.pattern for a field, and that's the only validation I have on my form.
Normal usage is working. It validates the field properly however the issue occurs when you try to copy and paste.
If you copy and paste on the field repeatedly on the field, it is like the validity of the field is being toggled( submit button is disabled if form is invalid )
Issue also occurs when I populate a the data from other source like search or auto-suggest.
buildForm(obj) {
this.form = this.fb.group({
field: [obj['field'] || '', Validators.pattern(/MY_REG_EX_HERE/g)],
id: [obj['id'] || ''],
});
}

I am not really sure about the main cause of the issue but as a workaround, I created custom validator with same REGEX. I will post it here and might help someone.
import { AbstractControl, ValidationErrors, ValidatorFn } from '#angular/forms';
export function customValidator(control: AbstractControl) {
if (control.value !== '') {
const isValid = (/MY_REG_EX_HERE/g).test(control.value)
return isValid ? null : { customValidator: true };
} else {
return null;
}
}

I had a similar problem. I studied it in detail and found out the reason. Like me, you are using the /g modifier. which has a side effect if the regex is assigned to a variable. This modifier indicates the continuation of the search in the string. To understand the "unexpected" behavior, take a look at the screenshot.
You can find out more information here

Related

Property 'name' does not exist on type 'string'

I have a list of objects and I need to iterate over the list and add a certain property (string) from the object to a map of <string, boolean>. Here is my code:
this.selectedPeople.forEach(element => {
this.checkedPeople.set(element.name, true);
}
The purpose of this is to set checkboxes to be checked for certain people (if they are in the selectedPeople list) using [checked] in Angular. For some reason, I get this error when trying to build the project:
Property 'name' does not exist on type 'string'
I tried to change element.name to just element and that provides errors during compilation but when I look at the frontend, none of the checkboxes are checked (as you would expect since the key in the map is not a string as required). I have done similar things with other lists and they seem to be working fine, so why is this an issue here?
Edit1: I have seen some other solutions on here but they do not seem to be relevant to my case or have not worked.
Edit2: This is not the actual code as it is company code so I have tried to recreate the issue using a different scenario so as not to run into any confidentiality issues. To elaborate further, the selectedPeople array would be something like this:
[
{
"name":"Paul",
"age":24,
"sport":"Football"
},
{
"name":"Tom",
"age":22,
"sport":"Tennis"
}
]
Edit3: For further clarification, here is what my checkedPeople map looks like:
0: {"Paul" => false}
1: {"Jennifer" => false}
2: {"Georgia" => false}
3: {"Tom" => false}
And I am trying to change the value to true for each person who is in the selectedPeople array.
I tried using element['name'] instead of element.name and that seemed to do the trick. I do not quite understand why this works (especially given that element.name is used elsewhere and works fine) so if anyone has any idea, feel free to comment.
Without seeing your project setup, I'm betting that typescript thinks that element can be a string or an object... something like this:
type SelectedPeople = Array<string | { name: string }>
In such as case, you will need to make sure the item is not a string before accessing the name property:
this.selectedPeople.foreach(element => {
if(typeof element === 'string') {
this.checkedPeople.set(element, true);
} else {
this.checkedPeople.set(element.name, true);
}
}
Yes, you can either try what Ryan is suggesting above, or alternatively you can add a safe check before setting each element like so:
this.selectedPeople.forEach(element => {
If (element && element.Name){
this.checkedPeople.set(element.name, true);
}
}

Angular autocomplete search

I have a dropdown where I get some json data. I am doing this in angular. So here I have a List named options where the data is in json format inside. So I have to display the name field at dropdown So my task here is to do a autocomplete search on this dropdown. I have attached my stackblitz link here.
You need to fix your filter method as:
private _filter(value: any): any {
const filterValue = value.toLowerCase();
return this.options.filter(option =>
option.name.toLowerCase().includes(filterValue)
);
}
Here is the demo code
You are comparing an object with the filter value.
Your filter callback function should be like this.
option => option.name.toLowerCase().includes(filterValue)
It's solved your problem.
return this.options.filter(option => option.name.toLowerCase().indexOf(filterValue) === 0);

How to pass cardElement to createPaymentMethod(cardElement, customerId, priceId) React+Stripe?

I have their <CardSection /> element in a SignUp form component, on submit I authenticate the user, create the customer, but can't figure out how to pass the <CardSection /> to the createPaymentMethod function.
Some of what I have:
SignUp form:
handleSignUp = (event) => {
event.preventDefault();
let cardElement = document.getElementById('#cardElement');
signUp(this.state.email, this.state.password, cardElement);
}
Where signUp() looks like:
import firebase from './firebase.js';
import { createCustomer } from './createCustomer.js';
import { createPaymentMethod } from './createPaymentMethod.js';
export function signUp(email, password) {
firebase.auth().createUserWithEmailAndPassword(email, password).catch(function(error) {
// Handle Errors here.
console.log(`Error in signUp ${error.code}: ${error.message}`);
});
createCustomer().then((customer) => {
let customerId = customer.customer.id;
let priceId = "price_HIsuBNTXc2NQ7L";
createPaymentMethod(cardElement, customerId, priceId);
});
}
This doesn't work (I get TypeError: JSON.stringify cannot serialize cyclic structures.), and I think I'm doing this plain incorrectly. What's the right way to do this part?
The documentation (https://stripe.com/docs/billing/subscriptions/fixed-price) seems to skip this step going from step 4 to 5. I'm pretty green with Stripe and React so take it easy on me. What am I missing here?
I believe Erwan Daniel's comment is correct and your signUp function is missing an argument. Its signature should probably be:
export function signUp(email, password, cardElement)

Grab data from Yahoo Finance using Meteor Package, some work some do not

I am using the following package for Meteor https://atmospherejs.com/ajbarry/yahoo-finance
I cant seem to get a specified field to work, here is a link that contains a list of all the available fields, however 'j2' and some others I tested don't work, in the sense there is no response in the result object, or no json key pair values.
Heres is my client side code.
Template.stock.rendered = function (){
if ( _.isEmpty(Session.get('ENW.V')) ) {
Meteor.call('getQuote', 'ENW.V', function(err, result) {
Session.set('ENW.V', result['ENW.V']);
console.log(result)
});
}
}
Template.stock.helpers({
stock: function() {
return Session.get('ENW.V');
}
})
Server side Method
Meteor.methods({
getQuote: function( stockname ) {
return YahooFinance.snapshot({symbols: [stockname] , fields:['n','a','b','j2'] });
}
});
Thanks for any Help in Advance. Happy to add any additional info if needed.
Did a test run after commenting out that line and it seems to work fine. Create an issue with the package owner to see if you can have it fixed for the long run.
The package you are using is deliberately excluding those fields. For what reason, I cannot say. For a full list of fields that it is avoiding, look here:
https://github.com/pilwon/node-yahoo-finance/blob/master/lib/index.js#L122

Angular.js binding checkbox value to mySQL bit

I am working on setting up an application using an Angular, Express, Node, mySQL stack and I am having an issue binding the value of a checkbox. mySQL stores boolean values as a bit so the json response is coming back with { done: 1 }, however angular seems to only accept boolean or string values to bind to true/false.
I have the following model (I have also tried defining done as DataTypes.BOOLEAN to no avail):
var Todo = sequelize.define('todos', {
text: DataTypes.STRING,
done: DataTypes.INTEGER
})
my code is setting the values for that model to this:
{"todos":[
{"id":1,"text":"add my first todo","done":1},
{"id":2,"text":"Get the done toggle working","done":0}
]}
Lastly in my view I have this code (I am using jade):
li(ng-repeat="todo in todos")
input(type="checkbox", ng-model='todo.done')
{{todo.text}}
However the checkbox is not being checked. I have tried adding ng-true-value but since it only accept string values I can't set true to an integer.
How can I get angular to work with the bit value stored by the database?
Update: I have updated my node server to convert the value of done into a boolean which is working good. Is that the recommended solution or is there a better way to accomplish this? (this solution feels a bit hacky to me and I feel like there must be a built in way to accomplish this without rewriting the server response in node)
todos.retrieveAll(function(todos) {
if(todos) {
todos.forEach(function(todo) {
todo.done = Boolean(todo.done);
});
res.json({
todos: todos
});
} else {
res.send(401, "No todos found");
}
}, function(err) {
res.send(501, "Error retrieveing todos. Message: " + err);
console.log("Error: " + err);
});
<input type="checkbox" ng-model="mymodel.myvalue" ng-true-value="1" ng-false-value="0" value="myvalue">
The best way is to use ng-true-value and ng-false-value, I had an issue because my values were being sent as json_encoded array which meant that I had to include the quotes to make it compare correctly.
Script:
// this is the model object that is bound to by the checkbox (amongst other things)
// and in my case is "1" for true "0" for false - note this is an array as passed back from my data source so I am using [0] in the HTML ng-model - if you have a straight object then you would bind to myScopeBoundVar and it would be defines as something like {"active":1} or in my case the 1 would be a string.
myScopeBoundVar=[{"active":"1", "surname" : "Smith"}];
HTML
<input value="check" ng-model="myScopeBoundVar[0].active" ng-true-value="'1'" ng-false-value="'0'" class="ng-valid ng-dirty ng-valid-parse ng-touched">

Categories