Nativescript: Cannot set TextView's text property from within propertyChanged Event handler

Created on 5 Feb 2016  路  14Comments  路  Source: NativeScript/NativeScript

Aim: Setting a maxLength to TextView component (i.e. limit the input of a TextView to N chars max (for example 10) )

Issue: .text attribute is not applied when done from within propertyChanged Event

How to reproduce (attempts tries):

FIrst I tried in _XML_:

<TextView id="my-input" hint="some hint" maxLength = 10 />
<TextView id="my-input" hint="some hint" maxlength = 10 /> <!-- 2nd try -->
<TextView id="my-input" hint="some hint" length = 10 /> <!-- 3rd try -->

with no luck

Then _programmatically_ (view's controller)

import textViewModule = require("ui/text-view");

let commentInputView = getViewById(page, "my-input")
commentInputView.on(textViewModule.TextView.propertyChangeEvent,  function(
eventData: ObservableEventData){
   console.log(eventData.propertyName == "text" && eventData.value.length > 
10);
   if (eventData.propertyName == "text" && eventData.value.length > 10) {
      eventData.value = eventData.value.substr(0, 9);
      commentInputView.text = eventData.value.substr(0, 9); // 2nd try

   }
 });

with no luck either.
the event is _triggered_, the _if_ is correctly satisfied and _substr_ returns
the correct value.
Also, if I set _.text_ property _outside_ of the event it just works, but _not
from inside_ the event handler.

_Output of console.log_:
JS: false [10 times]
JS: true
JS: true
... (true, true, ...)

Most helpful comment

wow, nobody?

All 14 comments

Well I'm pretty sure if their is not a valid max length property; but I wanted to comment on your xml. Even if their was a valid length property, your xml is malformed and won't work. All properties need to be inside quotes; your xml should look like this:

<TextView id="my-input" hint="some hint" maxLength = "10" />
<TextView id="my-input" hint="some hint" maxlength = "10" /> <!-- 2nd try -->
<TextView id="my-input" hint="some hint" length = "10" /> <!-- 3rd try -->

To s

@NathanaelA thanks for your contribution. You're totally right. However the JS code doesn't work either

That is because the event is after the text is set, which is what fires the event. The easiest way to fix your code would be:

let commentInputView = getViewById(page, "my-input")
commentInputView.on(textViewModule.TextView.propertyChangeEvent,  function(
eventData: ObservableEventData){
   if (eventData.propertyName == "text" && eventData.value.length > 10) {
      setTimeout(function() { commentInputView.text = eventData.value.substr(0, 9); }, 0);
   }
 });

However, if I was actually wanting to set the max size, I would actually set the maxWidth on the native control so it never ever gets to the point of firing this event. Which is the best way to solve it ;-)

Thanks @NathanaelA .

I tried doing (tested on Android)

if (frameModule.topmost().android) commentInputView.android.maxWidth = 10;

However it let's me add way more than 10 chars. (I also tried to set maxWidth in the XML but I guess it's not what you meant)

Your fix to event handler works.
Also, I don't understand: said that I'm aware that in pure JS (not {N}) event bubbling is handled the way you said, why should the text setting fail? I mean: the event is triggered after the text is set by the user but I don't see why the text can't be updated programmatically after user input. is setting the text an event itself?

@dragGH102

  1. To my knowledge their is no "maxWidth" value; so attempting to set it in xml or in JS won't do anything.
  2. The event that is bubbling up is an event that is put on the change of the value.
  1. To my knowledge their is no "maxWidth" value; so attempting to set it in xml or in JS won't do anything.

I guessed so.
However I don't yet get why maxWidth is not working in JS (so that I will also close this issue afterwards as it's not a "real" issue)

Well, if it isn't a property on the control it won't do anything no matter how you set it. You can use properties that you set in your own code; but the actual underlying code for the control can't use it since it hasn't been programmed for it.

@NathanaelA Which import did you use for your solution ?

let commentInputView = getViewById(page, "my-input") commentInputView.on(textViewModule.TextView.propertyChangeEvent, function( eventData: ObservableEventData){ if (eventData.propertyName == "text" && eventData.value.length > 10) { setTimeout(function() { commentInputView.text = eventData.value.substr(0, 9); }, 0); } });

I'm using Nativescript with Angular, and I don't be able to import ObservableEventData.

Just do a
declare var ObservableEventData: any; to make TS happy.

Ok.
I did this but the part below doesn't have the expected behaviour for me :
setTimeout(function() { commentInputView.text = eventData.value.substr(0, 9); }, 0); } });

The problem is that the input value is changed once time, and cursor is set at the beginning of the textview.

Do you have any solution ?

Anyone got this working?

wow, nobody?

I too have encountered this problem. To solve this, I disabled the submit button and put a message saying over limit. That way the user doesn't lose anything they may have thought they were typing, but have a chance to edit their text appropriately.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings