8000 safe navigation operator ( ?. ) and null property paths · Issue #4638 · vuejs/vue · GitHub
[go: up one dir, main page]

Skip to content

safe navigation operator ( ?. ) and null property paths #4638

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
saivarunk opened this issue Jan 3, 2017 · 16 comments
Closed

safe navigation operator ( ?. ) and null property paths #4638

saivarunk opened this issue Jan 3, 2017 · 16 comments

Comments

@saivarunk
Copy link
saivarunk commented Jan 3, 2017

Feature Request

Problem

While accessing the data from view in template expression, if a null object is used like below :

{{  book  }} 

View is rendered and displayed value is blank.

Suppose the template expression involves a property path, as in this next example where we’re displaying the name of a null book.

{{  book.name  }} 

This would throw a null reference error :
TypeError: Cannot read property 'name' of null.

Workaround

We can find a workaround for this using a conditional block like this:

<div v-if="book">
{{  book.name  }} 
</div>

But if we have a use case where we need a property path deep into the object some thing like this ?

a.b.c.d

Solution

We can use a safe navigation operator ( ?. ) or elvis operator similar to Angular 2. That can help in reducing a lot of conditional tags in a complex code.

@yyx990803
Copy link
Member

Thanks for the suggestion, but I'm not a fan of the idea of introducing non-standard syntax into template expressions - which imo should be "just JavaScript" as much as possible. Also if you have a deep path that may or may not exist on each level of access, it sounds like code smell to me. Your model/state should be as predictable as possible.

@WebDev2013
Copy link
WebDev2013 commented Aug 17, 2017

In Vue, how does one handle the situation where book is loaded async, and initially has no value?

@AbdallahBedir
Copy link
AbdallahBedir commented Sep 18, 2017

@saivarunk It gives me an error .//vue-loader/lib/template-compiler.js?id=data-v-8e3d2b58!.//vue-loader/lib/selector.js?type=template&index
(Emitted value instead of an instance of Error) template syntax error invalid expression: v-bind:value="model.topics?.id

@lehni
Copy link
lehni commented Dec 7, 2017

Optional chaining (elvis operator) is stage-1 now:

https://github.com/tc39/proposal-optional-chaining

Could this be reconsidered? I'd love to see it added, as it can beautifully simplify code.

@sirlancelot
Copy link
sirlancelot commented Dec 7, 2017

@lehni If optional chaining becomes available in Babel, then all you would need to do is enable the Babel plugin, there's no need for Vue to support this syntax since it's just JavaScript.

Update: I found this @babel/plugin-proposal-optional-chaining so it could already work

@lehni
Copy link
lehni commented Dec 7, 2017

@sirlancelot I am already using this plugin, and it works in JS code, but it does not work within the template expressions, e.g.

{{ book?.name }}

@sirlancelot
Copy link

My bad, it looks like template compilation uses a customized version of Buble, not Babel... https://vue-loader.vuejs.org/en/features/es2015.html#es2015-in-templates

@lehni
Copy link
lehni commented Dec 8, 2017

Oh I see, that explains a few things. I guess that means there's no flexibility here, except for if Vue would allow both engines to be plugged in for transpilation, using babel if it's there, falling back to buble if not. No idea if that's even possilbe.

@LeeMeyer
Copy link

in case anyone else comes here wanting to do this, I ended up using lodash lodash's get function which lets you do things like

_.get(a, 'b.c.d', 'optionalFallbackValueGoesHere')

to make this "get" function available to Vue I do

import lodashGet from 'lodash/get'
Vue.prototype.$get = lodashGet

in my entry.js

now in my Vue template I can use

{{ $get(a, 'b.c.d') }}

or if you want all of lodash available in your Vue templates you can use vue-lodash

I understand Evan You does not want Vue templating to morph into its own mutant language, but I don't agree having nullable properties with subproperties is a code smell, especially with the way I design my Vuex state with lookups by Id where additional information about a record may or may not exist

luckily Vue seems flexible enough that you can do anything JS from within a template, so it's all good once you get the hang of it :)

@sqal sqal mentioned this issue Aug 6, 2018
@Acionyx
Copy link
Acionyx commented Nov 11, 2019

https://github.com/tc39/proposal-optional-chaining
Stage 3 now (and half-way to Stage 4).

@yyx990803, Maybe it is a time to implement it now?

@lehni
Copy link
lehni commented Nov 11, 2019

It would need to be added to https://github.com/yyx990803/buble which was forked from https://github.com/bublejs/buble

@Acionyx
Copy link
Acionyx commented Nov 12, 2019

It would need to be added to https://github.com/yyx990803/buble which was forked from https://github.com/bublejs/buble

Actually it should be added to Vue itself, because it throws Errors before any transpiling happens.

@natebgurutech
Copy link
natebgurutech commented Dec 6, 2019

Just as a reminder, it's a little ugly, but javascript does have a safe traversal in a way.

from
dog.name
to
(dog || {}).name || null

from
person.job.salary.american()
to
((((person || {}).job || {}).salary || {}).american || () => null)()

But yes, person?.job?.salary?.american() would be much nicer

@karladler
Copy link

It's 2020 and optional chaining is already implemented in ecmascript. When can we expect it to work in Vue templates?

https://github.com/tc39/proposal-optional-chaining

@msklvsk
Copy link
msklvsk commented Apr 9, 2020

I guess someone should take courage and open this as a new issue.

@haoqunjiang
Copy link
Member

See #11088

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

0