:wave: How does the new `BasicTextField2` API conj...
# compose
n
đź‘‹ How does the new
BasicTextField2
API conjugate with non-compose state holders? I mean, let's say you have a ViewModel shared with other platforms and some of those platforms are not using Compose. The "good" way of using BTF2 is to store a
TextFieldState
with which you can use all the fancy
edit
API. But what if I can't store Compose things in my state holder because it's not exclusively used by Compose UIs?
Oh, and I know that you can use the basic string API but then you can't edit the text programmatically (or it won't be updated on the UI) so that's not always an option.
f
Without knowing your VM, just an idea. Maybe you can create a textfield state using deriveStateOf with the info that your viewmodel expose
n
This was more a theoretical question than a concrete issue with one of my projects, but I get your idea. I don't think that's the way to go, though, because you wouldn't be able to edit the text programmatically in the VM layer, which is the desired place.
f
Ah, on a theoretical side. My approach in that case is to don't attach a common VM to Compose and Android Views. I duplicate it if possible or change the VM to works in both cases. That in this particular case could be possible exposing whenever the view need and also the state. But man is ugly as hell xDDD
n
Unsatisfying solution just for the TextField, haha. I'm sharing ViewModels with JS and iOS in some projects, for example.
f
argh
h
because you wouldn't be able to edit the text programmatically in the VM layer
Can you give some examples to this? What is blocking you from implementing the filtering functionality in the UI layer, or call ViewModel functions from
inputTransformation
?
We are very interested in hearing these use cases that make
BasicTextField2
API difficult to work with compared to existing APIs.
e
You might have to drop a level lower and go expect+actual or interface+platformImplementation
k
You can have a
StateFlow
as data holder and in compose you can do
stateFlow.collectAsState()
n
Ok, let's try to bring it to concrete. Let's say you have an application for iOS, Android and web. The iOS and the Android app are using Compose Multiplatform and the web app is written in JS. All of the three share the VM layer and below using KMM. Now for the use case: Imagine the Instagram app. When you click on "reply" on a comment, the text field of the comment prepends the username of the replied user. Until now, given that the text was stored as a string on the ViewModel this was easily achievable. But now, for this kind of modifications (prepend, clear, append, and such) you need to perform them in the
TextFieldState
, otherwise, the changes won't propagate to the UI until the field loses focus. But
TextFieldState
is a Compose class. Propagating that to the ViewModel is not possible in this context. > What is blocking you from implementing the filtering functionality in the UI layer, or call ViewModel functions from inputTransformation ? > It's not filtering or calling the ViewModel what I want to achieve. I'm trying to modify the text in the ViewModel. I hope it's more clear now! > go expect+actual or interface+platformImplementation > This feels way more complex than before just for a TextField. > You can have a StateFlow as data holder and in compose you can do stateFlow.collectAsState() > I don't see how this helps.
To be super clear, the same behaviour is achievable; it's just that it's harder to achieve. For example, by sending a one time event from the VM to the UI and delegate into the view the edition.
a
The overload that takes
String
and
(String) -> Unit
will still be available, so you should be able to do whatever you can do now with that overload.
n
If the Medium post that was written by the compose team is correct, modifying the string won't affect the UI until the TextField loses focus.
a
What medium post?
n
https://proandroiddev.com/basictextfield2-a-textfield-of-dreams-1-2-0103fd7cc0ec
However, the text field won’t update the state with your programmatic changes while the field is in focus, it respects only the input coming from typing events
a
Okay I see the problem. So basically the new API sacrifices some flexibility for robustness. In that case, I would say using expect/actual class is the best way. I think it needs even less code than the one-shot event approach. It's more complicated than before, yes, but with this change your text field will also be more robust.
Also I don't quite understand how you can achieve what you want with string only now. Don't you need to place the cursor at the end when you prepend the text?
k
I can see this is not a problem in compose. Like you said it is achievable hard but not impossible to your requirement. You can see the overloads just receiving just text and inside handle with
TextFieldState
n
Don't you need to place the cursor at the end when you prepend the text?
Ah, you're right. Since this wasn't a real case but a theoretical one I missed the fact that you have to store TextFieldState on BTF1 for the same behaviour. So expect/actual feels like the way to go in the current case too.
You can see the overloads just receiving just text and inside handle with TextFieldState
Yes, I know the existence of this overload. But as it was already stated, this isn't usable because the UI won't update until the text field loses focus. Anyway, @Halil Ozercan, in case you want a usecase that is not covered by the BTF2 API (it wasn't exactly covered by the BTF1 either).
112 Views