Home > database >  How can I fix substring to read urls from object correctly?
How can I fix substring to read urls from object correctly?

Time:12-08

As the user is typing in a url, I am trying to iterate through an object so that no error message is thrown until a substring doesn't match the beginning of any of the urls in my object.

Object:

export const urlStrings: { [key: string]: string } = {
  'www.costco.com': '',
  'www.walmart.com': '',
  'www.google.com': '',
  'www.facebook.com': '',
}

So the user will type and no error will be thrown until a substring is incorrect:

w
ww
www.
www.c
www.ca <--- this should throw error

However, because I have subString set to 1, it only gives me the first letter of the url (item). I want to get everything from the first letter to the increasing index. I have a break in there that stops the for loop.

const correctUrl = (value: string | null): string => {
  let errorMessage = ''
  let item: string
  let subString = 1

  if (value && typeof value === 'string') {
    // eslint-disable-next-line guard-for-in
    for (item in urlStrings) {

      if (value?.length <= item?.length && subString <= item?.length) {
        if (item.substring(0, subString) === value.substring(0, subString)) {
          errorMessage = ''
          break
        }
      }
      subString  = 1
    }
  } else {
    errorMessage = 'Throw error'
  }
  return errorMessage
}

Any recs? Also, this is typescript.

CodePudding user response:

I think that's a bit more complicated than it needs to be. Array methods will make this pretty trivial. Put the keys of the object (the URLs) into an array, then check if .every one of those URLs does not start with the text typed. If so, then there are no potential matches, and you can return the error string.

const urlStrings = {
    'www.costco.com': '',
    'www.walmart.com': '',
    'www.google.com': '',
    'www.facebook.com': '',
};
const urls = Object.keys(urlStrings);
const correctUrl = (value: string | null): string => {
    if (value === null) {
        return 'Throw error';
    }
    return urls.every(url => !url.startsWith(value))
        ? 'Throw error' // None of the URLs matched
        : '';
}

The object of urlStrings seems a bit odd though. Unless the values of the object contain data in your actual code, you could consider starting out with a plain array instead.

const urls = [
    'www.costco.com',
    'www.walmart.com',
    'www.google.com',
    'www.facebook.com',
];

CodePudding user response:

good question!

First off, I'd recommend looking into guard clauses -- your nesting so many layers deep that the logic gets way more complicated to track with.

I think your Throw error is aligned with the wrong if statement -- basically if it succeeds at all, it's never going to throw the error. If you reformat your code with my first suggestion, I think the placement should be pretty clear -- and you shouldn't need a break statement.

Good luck, feel free to ask follow ups!

CodePudding user response:

It maybe easier to use JS's native array methods to help you. Add the keys to an array, and then use some to check the strings against the value of the input. If the value matches none of them throw the error.

const urlStrings = {
  'www.costco.com': '',
  'www.walmart.com': '',
  'www.google.com': '',
  'www.facebook.com': '',
};

const input = document.querySelector('input');
input.addEventListener('input', handleInput);

const validStrings = Object.keys(urlStrings);

function handleInput() {
  const { value } = this;
  const valid = validStrings.some(str => {
    return str.startsWith(value);
  });
  if (!valid) console.log('URL not valid');
}
<input type="text">

  • Related