zomdar
zomdar

Reputation: 273

how to return blank string if object is undefined in angularjs forms

I have a form model that I am using to map my form fields in AngularJS. Since I am updating these fields on a database I want to retrieve the fields once the user submits the form and comes back to it.

form object:

vm.user = {
        userBag:[
          {
            name: nameService.nameBag[0].organizationName
          },
          {
            name: nameService.nameBag[1].organizationName,
          },
          {
            name: nameService.nameBag[2].organizationName,
          }
        ]
  };

I have coded the form object to return the database fields but I'm running into an error when the user initially has nothing submitted in the field bc the object is empty. Getting the error:

"TypeError: Cannot read property 'organizationName' of undefined"

nameServie is just a get call that retrieves the get.

How do I make it so that the name fields just return a blank if the nameService is undefined?

Upvotes: 0

Views: 1308

Answers (3)

Alexander
Alexander

Reputation: 117

i just met the same problem. googling gave no results, but occasionally i have just solved very similar problem and imagined the following solution:

type Pipeline<T> =
  { [K in keyof T]: Pipeline<T[K]> }
  & { VALUE: (defaultValue: T) => T }
export function ppln<T extends {}>(value: T): Pipeline<T> {
  function bound(value: any): boolean {
    return ["string", "number", "boolean", "undefined", "function"]
      .includes(typeof value)
  }
  return new Proxy<T>(
    bound(value) ? {} as T : value, {
    get: (_, field: keyof T) => {
      if (field === "VALUE") {
        return defaultValue => value === undefined ? defaultValue : value
      }
      if (value && value[field]) {
        return ppln(value[field])
      }
      return ppln(undefined)
    }
  }) as unknown as Pipeline<T>
}

then it should be possible to do

ppln(obj).prop1[prop2].prop3.VALUE()
ppln(obj).prop1[prop2].prop3.VALUE('default value')

and get either existing value or undefined without an exception. second line will produce 'default value' if requested value is undefined.

Upvotes: 0

Raeesaa
Raeesaa

Reputation: 3316

You can use ternary operator to achieve it:

 vm.user = {
        userBag:[
          {
            name: (nameService && nameService.nameBag && nameService.nameBag[0]) ? nameService.nameBag[0].organizationName : ""
          },
          {
            name: (nameService && nameService.nameBag && nameService.nameBag[1]) ? nameService.nameBag[1].organizationName : ""
          },
          {
            name: (nameService && nameService.nameBag && nameService.nameBag[2]) ? nameService.nameBag[2].organizationName : "",
          }
        ]
    };

Upvotes: 2

J. Pichardo
J. Pichardo

Reputation: 3115

There are several ways to accomplish what you want:

Ternary operator

Using a ternary operator you could have something like:

vm.user = {
  userBag:[
    {
      name: nameService ? nameService.nameBag[0].organizationName : ''
    },
    {
      name: nameService ? nameService.nameBag[1].organizationName : ''
    },
    {
      name: nameService ? nameService.nameBag[2].organizationName : ''
    }
  ]
};

Or operator

With the || operator you can evaluate if the path you want to access "exists" or has value:

{
  name: (nameService && ... && nameService.nameBag[0].organizationName) || ''
}

Optional Access Function

However in order to keep things DRY I would rather use a function for optional access, something like:

function optionalAccess(obj, path, def) {
  const propNames = path.replace(/\]|\)/,'').split(/\.|\[|\(/);

  return propNames.reduce((acc, prop) => acc[prop] || def, obj);
}

const obj = {
  items: [{ hello: "Hello" }]
};

console.log(optionalAccess(obj, "items[0].hello", "def")); // prints: Hello
console.log(optionalAccess(obj, "items[0].he", "def")); // prints: def

TC39 Proposal

There is currently a proposal in order to be able to use chaining, which would allow you to do something like:

nameService?.nameBag[0]?.organizationName || ''

If you want to do something like that there is also the babel plugin

https://www.npmjs.com/package/babel-plugin-transform-optional-chaining

Upvotes: 0

Related Questions