1+ // https://gist.github.com/chrismccord/c4c60328c6ac5ec29e167bb115315d82
2+ // maintain backwards compatibility of phx-feedback-for, which was removed in LiveView 1.0
3+ // find all phx-feedback-for containers and show/hide phx-no-feedback class based on used inputs
4+ import { isUsedInput } from "phoenix_live_view"
5+
6+ let resetFeedbacks = ( container , feedbacks ) => {
7+ feedbacks = feedbacks || Array . from ( container . querySelectorAll ( "[phx-feedback-for]" ) )
8+ . map ( el => [ el , el . getAttribute ( "phx-feedback-for" ) ] )
9+
10+ feedbacks . forEach ( ( [ feedbackEl , name ] ) => {
11+ let query = `[name="${ name } "], [name="${ name } []"]`
12+ let isUsed = Array . from ( container . querySelectorAll ( query ) ) . find ( input => isUsedInput ( input ) )
13+ if ( isUsed || ! feedbackEl . hasAttribute ( "phx-feedback-for" ) ) {
14+ feedbackEl . classList . remove ( "phx-no-feedback" )
15+ } else {
16+ feedbackEl . classList . add ( "phx-no-feedback" )
17+ }
18+ } )
19+ }
20+
21+ export default phxFeedbackDom = ( dom ) => {
22+ window . addEventListener ( "reset" , e => resetFeedbacks ( document ) )
23+ let feedbacks
24+ let submitPending = false
25+ let inputPending = false
26+ window . addEventListener ( "submit" , e => submitPending = e . target )
27+ window . addEventListener ( "input" , e => inputPending = e . target )
28+ // extend provided dom options with our own.
29+ // accumulate phx-feedback-for containers for each patch and reset feedbacks when patch ends
30+ return {
31+ onPatchStart ( container ) {
32+ feedbacks = [ ]
33+ dom . onPatchStart && dom . onPatchStart ( container )
34+ } ,
35+ onNodeAdded ( node ) {
36+ if ( node . hasAttribute && node . hasAttribute ( "phx-feedback-for" ) ) {
37+ feedbacks . push ( [ node , node . getAttribute ( "phx-feedback-for" ) ] )
38+ }
39+ dom . onNodeAdded && dom . onNodeAdded ( node )
40+ } ,
41+ onBeforeElUpdated ( from , to ) {
42+ let fromFor = from . getAttribute ( "phx-feedback-for" )
43+ let toFor = to . getAttribute ( "phx-feedback-for" )
44+ if ( fromFor || toFor ) { feedbacks . push ( [ from , fromFor || toFor ] , [ to , toFor || fromFor ] ) }
45+
46+ dom . onBeforeElUpdated && dom . onBeforeElUpdated ( from , to )
47+ } ,
48+ onPatchEnd ( container ) {
49+ resetFeedbacks ( container , feedbacks )
50+ // we might not find some feedback nodes if they are skipped in the patch
51+ // therefore we explicitly reset feedbacks for all nodes when the patch
52+ // follows a submit or input event
53+ if ( inputPending || submitPending ) {
54+ resetFeedbacks ( container )
55+ inputPending = null
56+ submitPending = null
57+ }
58+ dom . onPatchEnd && dom . onPatchEnd ( container )
59+ }
60+ }
61+ }
0 commit comments