Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Error changing properties of an element through ref #1012

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
vallemar opened this issue Dec 6, 2022 · 11 comments · Fixed by #1044
Closed

Error changing properties of an element through ref #1012

vallemar opened this issue Dec 6, 2022 · 11 comments · Fixed by #1044
Labels
V3 Issues related to V3

Comments

@vallemar
Copy link
Contributor

vallemar commented Dec 6, 2022

When I try to animate a view using ref to access the template element the app crashes and closes, but I can't see any errors. Code:

const btnNewTrip = ref()
const btnShowMore = ref()

const showButton = (view: View) => {
    view.animate({
      scale: {
        x: 1,
        y: 1
      },
      duration: 500
    })
}

onMounted(() =>{
  setTimeout(() => {
    console.log(btnNewTrip.value.nativeView)

    showButton(btnNewTrip.value.nativeView)
    showButton(btnShowMore.value.nativeView)
  }, 5000)
})

The console log shows me that it is a view, however the app fails, console.log: JS: StackLayout(46)
By the way, i'm on android

@rigor789 rigor789 added the V3 Issues related to V3 label Dec 6, 2022
@rigor789
Copy link
Member

rigor789 commented Dec 6, 2022

Huh, that's odd - a reduced example shows the same behavior (without using refs), the opacity animates in, but scale does not. Will need to check in a fresh core app to compare, because I can't think of anything we do that would affect this on the vue side.

Updated: This doesn't work either - only when triggered a 2nd time with the tap. 🤔

<script lang="ts" setup>
function animateIn(args) {
  const view = args.object;
  view.color = "green";
  view.scaleX = 0;
  view.scaleY = 0;

  view
    .animate({
      opacity: 1,
      scale: {
        x: 1,
        y: 1,
      },
      duration: 3000,
    })
    .then(() => {
      view.color = "red";
    })
    .catch((err) => console.log(err));
}
</script>

<template>
  <Button
    ref="btnNewTrip"
    opacity="0"
    scaleX="0.1"
    scaleY="0.1"
    @loaded="animateIn"
    @tap="animateIn"
  >
    New Trip
  </Button>
</template>

@rigor789
Copy link
Member

rigor789 commented Dec 6, 2022

This works, waiting 1ms. Super weird, not sure why.

<script lang="ts" setup>
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

async function animateIn(args) {
  await wait(1);
  const view = args.object;
  view.color = "green";
  // view.scaleX = 0;
  // view.scaleY = 0;

  view
    .animate({
      opacity: 1,
      scale: {
        x: 1,
        y: 1,
      },
      duration: 3000,
    })
    .then(() => {
      view.color = "red";
    })
    .catch((err) => console.log(err));
}
</script>

<template>
  <Button
    ref="btnNewTrip"
    opacity="0"
    scaleX="0.1"
    scaleY="0.1"
    @loaded="animateIn"
    @tap="animateIn"
  >
    New Trip
  </Button>
</template>

@vallemar
Copy link
Contributor Author

vallemar commented Dec 6, 2022

Yes, it's strange, because at that moment the view is supposed to be available, I don't know what it has to do with waiting 1ms 🤔

@vallemar
Copy link
Contributor Author

vallemar commented Dec 8, 2022

I can't get this to work, I don't even mention a wait(1000)

@heywhy
Copy link
Contributor

heywhy commented Dec 13, 2022

The animation does work when one listens for the loaded event on the element/component. The animation transforms the opacity property as expected, I'm not sure why it doesn't work for the scale properties but I believe it could be due to some layout calculation pending or done in the background.

NB: The loaded event gets triggered again when you navigate from the screen and return to it.

const animateButton = (view: View) => {
  view.animate({
     opacity: 1,
     duration: 500
  })
}
<template>
  <Button opacity="0" @loaded="animateButton($event.object)">New Trip</Button>
</template>

@vallemar
Copy link
Contributor Author

vallemar commented Dec 16, 2022

I'm having problems passing an imageSource as a ref to a function of a component. I think vue is not able to have reactive objects like these for some reason.

Could it be a problem with the new proxies?

@rigor789
Copy link
Member

I'm having problems passing an imageSource as a ref to a function of a component. I think vue is not able to have reactive objects like these for some reason.

Could it be a problem with the new proxies?

Do you have an example? I don't think you would want to wrap an imageSource as a ref though...

@vallemar
Copy link
Contributor Author

vallemar commented Dec 16, 2022

I know, it's weird, I'll change it to url and load the imageSource from within but, just as a note, if I do toRaw(value) it works as expected

    [startIconProperty.setNative](value?: ImageSource) {
        if (value && value.android) {
            try {
                const rawValue = toRaw(value) //.  <-- THIS
                const drawable = new android.graphics.drawable.BitmapDrawable(Utils.android.getApplicationContext().getResources(), rawValue.android);
                console.log(drawable)
                this.layoutView.setStartIconDrawable(drawable);
                this.layoutView.setStartIconTintList(null);
                this.layoutView.setStartIconTintMode(android.graphics.PorterDuff.Mode.MULTIPLY)

            }catch (e) {
                console.log("Error setting startIcon")
                console.log(e)
            }
        } else {
            this.layoutView.setStartIconDrawable(null);
            this.layoutView.setStartIconOnClickListener(null);
        }
    }

Could something like this also happen with the animations? I have commented for that

EDIT: what was failing at this point was when accessing value.android, if I did console.log(value) I could see that the object had an android property but nevertheless if I tried to access it the application would close

@vallemar
Copy link
Contributor Author

It is also strange that this with dominative worked, so how are we inserting the nativeView element?

@vallemar
Copy link
Contributor Author

vallemar commented Dec 16, 2022

sorry to be so heavy lol what if we let .value be the native view? that vue manage the dom I mean, I say it because I think you are already prepared for this

@vallemar
Copy link
Contributor Author

vallemar commented Dec 22, 2022

Confirmed, I've put all my animations under toRaw and it's working for me. I don't know if I have any setTimeout out there since they are some utilities that I have from other projects using the compositionApi and now everything works

  const panel: View = toRaw(viewPanel.value?.nativeView)

but before it worked and now it doesn't

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
V3 Issues related to V3
Development

Successfully merging a pull request may close this issue.

3 participants