Elm onInput event handler not working on contenteditable element - dom-events

I want to update my model everytime someone modifies an editable table cell.
The onInput function seems to be working well on input elements, but on a td element with contenteditable="true", the handler function never gets called.
Why?
How should I detect content change in an editable table cell then?
Please see lines 74 and 78 in the following piece of code
(I just took the "buttons" example of the Elm guide and added my stuff to it to have something minimal but runnable):
module Main exposing (..)
-- Press buttons to increment and decrement a counter.
--
-- Read how it works:
-- https://guide.elm-lang.org/architecture/buttons.html
--
import Browser
import Html exposing (Html, button, div, text, table, tbody, tr, td, input)
import Html.Events exposing (onClick, onInput)
import Html.Attributes exposing (contenteditable)
-- MAIN
main =
Browser.sandbox { init = init, update = update, view = view }
-- MODEL
type alias Model = Int
init : Model
init =
0
-- UPDATE
type Msg
= Increment
| Decrement
update : Msg -> Model -> Model
update msg model =
case msg of
Increment ->
model + 1
Decrement ->
model - 1
testOnInputHandler : String -> Msg
testOnInputHandler str =
let
log = Debug.log "in testOnInputHandler" "here"
in
Increment
-- VIEW
view : Model -> Html Msg
view model =
div []
[ button [ onClick Decrement ] [ text "-" ]
, div [] [ text (String.fromInt model) ]
, button [ onClick Increment ] [ text "+" ]
, table []
[ tbody []
[ tr []
[ td [ contenteditable True, onInput testOnInputHandler] [ text "editable!" ]
]
]
]
, input [ onInput testOnInputHandler ] []
]

onInput will get the string from target.value which does not exist for contenteditable input events.
You may want to grab innerText for example instead:
onContentEditableInput : (String -> msg) -> Attribute msg
onContentEditableInput tagger =
Html.Events.stopPropagationOn "input"
(Json.map (\x -> ( x, True )) (Json.map tagger innerText))
innerText : Json.Decoder String
innerText =
Json.at ["target", "innerText"] Json.string

Related

Couchbase N1q1 update array element and return only the updated block

I want to update an element in an array object and return only the few elements from the updated array object.
Document:
{
"doctype" : "report",
"name":"nick",
"emailId":"nick123#gmail.com",
"subjects" : [{
"name":"SOA",
"tutor":"roshan",
"classes" : "12",
"mark" : 40,
"subid": "5678"
},
{
"name":"UNIX",
"tutor":"mathew",
"classes" : "9"
"mark" : 50,
"subid" : "3788"
}
],
"id" : "12345"
}
n1q1:
update bucket1
Set i.status = “pass” for i in subjects when i.mark > 40 end
where doctype = "report"
returning *
above query returns the whole document but I want only few element from the updated array object like below. Can you please help me on this . Thanks
Expected query response
{
"id" : "12345",
"subid: “3788”,
"name":"UNIX"
}
Returning clause you can build expression that you want.
You are updating ARRAY, it means it can update more than one element. so you can return as ARRAY, if you want FIRST element replace with ARRAY with FIRST.
UPDATE bucket1 AS b
SET i.status = "pass" FOR i IN b.subjects WHEN i.mark > 40 END
WHERE b.doctype = "report" AND (ANY v IN b.subjects SATISFIES v.mark > 40 END)
RETURNING (ARRAY {v.id, v.subid, v.name} FOR v IN b.subjects WHEN v.mark > 40 END) AS subjects;
You can only return modified info, you will not able to return original info.

How do I concatenate a dynamic string value using Groovy to JSON response after it's parsed to get a specific node value in JSON

slurperresponse = new JsonSlurper().parseText(responseContent)
log.info (slurperresponse.WorkItems[0].WorkItemExternalId)
The above code helps me get the node value "WorkItems[0].WorkItemExternalId" using Groovy. Below is the response.
{
"TotalRecordCount": 1,
"TotalPageCount": 1,
"CurrentPage": 1,
"BatchSize": 10,
"WorkItems": [ {
"WorkItemUId": "4336c111-7cd6-4938-835c-3ddc89961232",
"WorkItemId": "20740900",
"StackRank": "0",
"WorkItemTypeUId": "00020040-0200-0010-0040-000000000000",
"WorkItemExternalId": "79853"
}
I need to append the string "WorkItems[0].WorkItemExternalId" (being read from a excel file) and multiple other such nodes dynamically to "slurperresponse" to get the value of nodes rather than directly hard coding as slurperresponse.WorkItems[0].WorkItemExternalId..
Tried append and "+" operator but i get a compilation error. What other way can I do this?
slurperrsesponse is an object its not a string that's why the concatenation does not work
Json Slurper creates an object out of the input string. This object is dynamic by nature, you can access it, you can add fields to it or alter the existing fields. Contatenation won't work here.
Here is an example:
import groovy.json.*
​def text = '{"total" : 2, "students" : [{"name": "John", "age" : 20}, {"name": "Alice", "age" : 21}] }'
def json = new JsonSlurper().parseText(text)​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​
json.total = 3 // alter the value of the existing field
json.city = 'LA' // add a totally new field
json.students[0].age++ // change the field in a list
println json​
This yields the output:
[total:3, students:[[name:John, age:21], [name:Alice, age:21]], city:LA]
Now if I've got you right you want to add a new student dynamically and the input is a text that you've read from Excel. So here is the example:
json.students << new JsonSlurper().parseText('{"name" : "Tom", "age" : 25}')
// now there are 3 students in the list
Update
Its also possible to get the values without 'hardcoding' the property name:
// option 1
println json.city // prints 'LA'
// option 2
println json.get('city') // prints 'LA' but here 'city' can be a variable
// option 3
println json['city'] // the same as option 2

Is there a way to randomize the jsonPath array number in get[] myJson?

I have a list of values that I can use for the title field in my json request. I would like to store a function in the common.feature file which randomizes the title value when a scenario is executed.
I have attempted using the random number function provided on the commonly needed utilities tab on the readme. I have generated a random number successfully, the next step would be using that randomly gernerated number within the jsonpath line in order to retrieve a value from my data list which is in json.
* def myJson =
"""
{
"title" : {
"type" : "string",
"enum" : [
"MR",
"MRS",
"MS",
"MISS"
[...]
]
}
}
"""
* def randomNumber = random(3)
* def title = get[0] myJson.title.enum
* print title```
The code above works but I would like to randomize the number within the get[0]. How is this possible in Karate?
I'm not sure of what you want, but can't you just replace 0 by randomNumber in get[randomNumber] myJson.title.enum ?

In Elm, how can I detect if focus will be lost from a group of elements?

Suppose I have a form with a number of components. I'd like to detect a los of focus from the group. So, focus from 1 input to another on the same form should be ignored. How can I achieve this?
First, we want to be able to tag each focusable element within the group with some attribute, so when we switch elements we'll know if we're in the same group or not. This can be achieved with data attributes.
groupIdAttribute groupId =
Html.Attributes.attribute "data-group-id" groupId
Next, we need to decode the event payload on an onBlur event to see if the target is different from the relatedTarget (that which will get the focus). And report the change. (note that here we refer to data-group-id via the path "dataset", "groupId")
decodeGroupIdChanged msg =
Json.Decode.oneOf
[ Json.Decode.map2
(\a b ->
if a /= b then
Just a
else
Nothing
)
(Json.Decode.at [ "target", "dataset", "groupId" ] Json.Decode.string)
(Json.Decode.at [ "relatedTarget", "dataset", "groupId" ] Json.Decode.string)
, Json.Decode.at [ "target", "dataset", "groupId" ] Json.Decode.string
|> Json.Decode.andThen (\a -> Json.Decode.succeed (Just a))
]
|> Json.Decode.andThen
(\maybeChanged ->
case maybeChanged of
Just a ->
Json.Decode.succeed (msg a)
Nothing ->
Json.Decode.fail "no change"
)
Now we can create an onGroupLoss listener:
onGroupFocusLoss msg =
Html.Events.on "blur" (decodeGroupIdChanged msg)
And rig it up like so:
input [onGroupFocusLoss GroupFocusLoss, groupIdAttribute "a"]
Here is an example (note that it is built with elm-ui so there's a little extra code.)
https://ellie-app.com/3nkBCXJqjQTa1

Disable Elm form submission without no-op message

I have an Elm app with an HTML form (containing an input field and a submit button) that I would like to disable while the input is not valid. I've managed to do that by binding form submission to a no-op message when the input is invalid:
type Msg
= Input String
| Submit
| Noop
viewForm : Model -> Html Msg
viewForm = form [ onSubmit (if model.valid then Submit else Noop) ]
[ input [ onInput Input ] []
, button [ disabled (not model.valid) ] [ "Submit" ]
]
update then does nothing on a Noop message. The button is also disabled, but this is secondary, since I also care about form submission by hitting Enter from the text input. Note that it does not work to skip the onSubmit handler, because then hitting Enter will reload the page.
This feels a bit messy and inefficient, so my questions are:
What is the idiomatic way to achieve this in Elm?
How much more expensive is this use of a no-op message to a no-op Javascript event handler.
First of all, I have to say that your implementation is alright, there's no harm in sending Noop message, that's why it exists.
The best scenario would be to remove the listener entirely(if possible) and disable the button visually. This actually might have a performance drawback if model.valid changes super-frequently.
I'm using a helper for conditionally adding stuff to a list:
appendIf : Bool -> a -> List a -> List a
appendIf flag value list =
if flag == True then
list ++ [ value ]
else
list
So you could use it like that:
view model =
button
([ type_ "" submit ] |> appendIf model.valid (onClick Submit))
[]