From edc9aaf53d58b67b465a8ab94b35aeef6b5714d2 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 6 Feb 2024 09:43:57 -0500 Subject: [PATCH] Add dynamic parameter support --- netbox/project-static/dist/netbox.js | Bin 371023 -> 373193 bytes netbox/project-static/dist/netbox.js.map | Bin 336814 -> 338655 bytes .../src/select/classes/dynamicParamsMap.ts | 76 +++++++++++ .../src/select/classes/dynamicTomSelect.ts | 125 +++++++++++++++++- 4 files changed, 198 insertions(+), 3 deletions(-) create mode 100644 netbox/project-static/src/select/classes/dynamicParamsMap.ts diff --git a/netbox/project-static/dist/netbox.js b/netbox/project-static/dist/netbox.js index 98161e946008e85c4388afc25898d51071048ebc..dcae61988f71f198686fc1cba9548b65568b1b8b 100644 GIT binary patch delta 32570 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�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 delta 30499 zcma%kcX$&=`u{UKD?mazelG3`TXWpKgX(KBgohVzs z=kVNFfp*IVXNSiX&TjLB?LmLoAC3k*8(Ni3E(<&OGMOtWow2FpUa~3n9GN#`z02I{ z51M!n9yQh9n!4U)3ae&wXM60gWNt>#6OIIZsj51lSREFVsw#MCDTuW5WNW*qs;rBZ zOJ-6O>z3AxZ)+c_)weG8q+}u8F-kX_(ymud+Z1b}rNkY(fo3Ilx0}|vOq={@EY0GJ zc)f+Lc2gksG3_Vmhum^Dkz3rBqCFQGTh1HPCq`9Ex7yUMHs?D$ zraDtJ_RzZNBzowzb;fyNb4 zx`Y0JF(V_YW^Zo~;u&-8RM65TJNJyy%gkyk;8M=mhteZw0J_*mXUxOz>1U;kKm$32 z(U^MX>JbjF*C>*%k#f(O2;pU^YpWfz|{3;Eg^HQK1;xt-Rjvx18rC_Slj0jsZuvoxgB& zG&rD?ff6y=cg~-UR}Wv18C!6{(s*ju13AKw-huYsC0-RB`5OpxItqyO*KZyQUB4(+;bxs>HpE#Y=Gl-=U#_V~h~rcSI0Czg|?+poG)a{#wf zr)rnSiti%o|NWKoP|J-|3F<~}D!}i(H!a2QiJP3sXpQ5}%CEmsFpS$%0nV5^Y#>kj9s3M9s8OP#Ti#$A?;z|i z_xE^$R!7KVGV4h2dVFo+_JSfzxHC5Qk2BFi{vS*5d*&Y(;P>`F&Pu`H9B#MCC7Ln= zhNg(xY;nfk`Qzz3oNB7-OZ8)>yq<7si)z7JCy?F3Ny;nImXK;{;UtT8;=Sc&WB|8xM>4Fi1N%=fIsnwpgwc7(G z;}&CPr>Ynu;8tGFqGROVOTimWZq=OK=?DNUOMx|Z{k=69-*@*eBF;k#{8u6!VeC*|V}nLvKB30ed<${h^5xFthNHR{ZXHB>5DM1&))t*xiqC;9h!U)s8yV(xIAa zI28O{9`cxV}D5<`-yc$&rdfGhO@nzw#iN?^3 zDrQ-qg;v$$b?4dC0rLQFVE|mF#^n!sietMUeH_rOf2>=!sQ~QB$L4L+@r5}9Q8tyT z&Heqk=7GG{h|d*P{XP?~$C(f0KV~f_A9wl>SE{q$4LmQ(vpTOBxo?2k-=98)@zHWGZ2nqH4MvP!EAV9?F1di ziJ{fSu76?)fHeNu%|PWAZ|{bdFWJ4kZm4j1bk3bQcP>aWMFcB_q$y2SuFk8 zG>8Vy3I!*u!D1S$F8C>5W+;Ke>+k}mz_Xcy6)ZzFb-{zRo$XaS)iBneGxpfCVQ3M{ zpF5w6s>lCY297ZHNQ3yzWR{<#k+Ca|+=A?y=dU33u{WQ8lGqOIe}R&5ARApf2gNvJ zcfU9dSa|ludiSC)Qs@;zB@f8N2fm|+M|OoQ%a=hCWWSs; z*%q=aS*3LPElYEh2ES#cVmnm-vfp4tLtJOb7Yqq4di@SJxR0g65pIXv*p8+?d94V& zX1>n*E`NO)e$RNl7{AZH?wRBS>cO}ifq*v(QKL8y6~3{CGsm58Rn5Slfm={VThJc~ z)N$RinDZ+T-{)_g1^jlsz2KB6R|-L)(b$2v>sD3!EQ4lF)Th{emc}9aD)(9X1{8>K~#>X`uj68 zJA6txdhqc!0KHE1l|J);GiG`>b%)b$ar)wPvc{)$`tku^Fk}K`$TY1%Px?bZ24=n{ z3}N7mggqvs*WvVdjSweBBd=@I>*CSh@9<@2@-hyo{t(~0)etuV+<2vf7<>BN38W+T z+PiZ`;XA0*K+MnYHk~41iu!;>$9vQ2k$~=-m^Ndf)6e0{8!QH2gbuvj!Al``luckS zW(kVVd?Xmkm$%M)A!6%Kg?5fGQ+O2jMfPsSGhiB_zjVI=yTJ(e+M$L04vPN^cc#_c*wRxZSH@UsF8n2&un2mI@&&(bIWW0Nw-)Y!7mC!wh1^KHQ5q0bAT zUTv#Eu2GPz0)t0Dd-xSK_3`@sS0U}tSwgbg?kR<8LF#%7-jBEV^%nn6(5?A zNl$!HVBmO*#zuZ=HbjxK#g=`!R2JWNemR3DAd|kF9=qYodjUtoR|l>Zn@LEW_DwQ= zFaKr@8h-5?KOgKrxt`bdPun=q3OJHZ{T;FU|G8jF2gh?7kjqEmP<>fT!I!d z{uNq=Sx{47pBl_1lQoo*YGz%4_8k0H?bG~RS4XV|F#=e=GotV!#Qlv zcU-u<_#J1>zt@7IiV zeLq+9k_EHjk?*|*2vH1~Ggg($Ct-E!U4{4>g(%_*bQv1tHS&xzRw8U*5}BzzJ%JF4x=m9_Ci`|WnTGVZDdYfgvb&~`RwxJgH7c-B z(5XU`C=>(GrvjR477EcjEC?v!tDS635{HZ>PbD@0h$eFgvKJ(iFZ4&Mc2x>_2y>!s znn5PPQf3`9$ww`}8Uxp@p@<2=1>FpC45F^7Su9&HP!50s=82^z7J?9#CSCagg$dq^ zcibGQ;;LwWf0W%di)4=D>jCs9%#RNC@hk$T2%9yV%p!Gc)od~sNU@arVqMQpWx?5G z9!%G`XjjE*M4KT`757Iiv#ST->%*s+o5V$=KlZfgzx>(i3bR(Dhkvfp~#^ zpbX4gZxeE=+^1`boOXH3X%IquopH-ffVl=@Oglb@Y$39vUGXw&DluW2ys2cbfm>d6 zY-Ac)NW5%u8pMr*ZA>HcCIg_j9Uj*mob0?bk~bH2r;v?&xV&L#)ImpECs!3PdZ+e& z8tEjdqRRT9DHuZSY+sLXtxGC5#`=hC0}Rc_a^X^Y%QV zG+;^#6T^(-34#swDg?37=WhXHh4dAIN(Z|tot%UI(&m%-GXQ?BAR<8wTzYb?!DMc7YFp=%S7g*%x{y2!la0HHAX0QH zfe3=h#71TkFhtgqN#@~kbtcJx-X~0VRCd6!?DpvOF$NoZE0fGv2=g)M>GXG_j{!a< z;1RrKVF3)f6M5@SHdn#Yb+VNTNdrNrb;!vqppe<5PP<4UP68K{&^&}0qw}H&NKzY- zP1^Z7^e-Y{kL;2~Bn6LK7LoELT*npOA9!m(S0EuULasPLW+iM$FNmM}I#46GInSvr z$RP&aTvjfYmy^ZY%7akW7FBU%Q)cL*yZF_Ug^FSWDj~OT}d+W z2(KiY@i@AYz$jxASCNbn__D7l63hK=Dyv#W%=ol#6}g=XRi~L=vD+_|nW(7~#F( zX%z5^{rxq-qZ#vy3D?y!kDId-=t%?Iu!jGr209o3Q`ou!l0O0<6!h8H`30m1BYL5L z%t#SMm?U@>bz6d4hYUFkF?ge|mhETiT!0{f9g%g8;XUdvoZcER(<4poqRJie*`0ohr0C4qQnn=8o- zjH0KKK*M3IlH^NHmF1YoYzcV%S0xsrs5G5InPj;e$Xev9RtgDw$p(@+4Nwe<6uzW| zMvGyyS2lp*I@!L6s5`+9B6e!|b~3+pJk7F{_og9XJ-|8535u@Tg5{Xw3@Cf1Sh;1x#) z02&O{#i4P>wH5GukP}pvJ~zZf8)u_=MzLoAhRo^?e9-3%lo8kAdLz}V@Jggo4$F#^Xsw_ttNX>1E=mC)QTTS?t1 zKxaW8kl@ss9b^GT@!4*28jvn~$UGU#E$+;Mjvfj}y&hrwfd|AhT8T=2;gnOn4Vba9 zzHQ`jveOyK7)8~cXg3lm`30`eGTj(Q; z;bqgo1G5Cn!g%B3a=~k~4P)Z3IU@{}`(4{SZZJ@c#l|l63Eup$k5ps2Ci%&~Ffc=a z!0pZ&0;CoW7dW_8NQP36+SVRk#ED4PJoSPsCwnmfMYEbEb&;$I)xHAm0?|cQ*5a6> zeF}4RkxMY*Z@UQG_$)ohiCb$65-8F(b|geLSwPvsx=sb>gfFa*(;ld%l)G8;tA9l? z;6QFi7<(gOeb3KQ%^YFUjh0>yL%9KdBcuzD`y<4P$4?RRB_2DM&{=F`4}q!0miCYb zpcjAD1HPA6?KLZ5U$)!Rs=|qH>{f%}h{M~GFmvqUHMcT_=DQ7hx;~Ss(VXl%N~N|VN^YUx(53-WE?Lz>EqA<1Czp#|7rsBnhqDoTWNgb$NX@8rd?$Gyj(PUv znLvIu`{qn?+l*?}vQcdcLI14gDn^G$^F5Sm_NTK*)`)7ZIaF((oCW?f7L{{QZ*|C* zU(LGC0SByR7o0=pz&g489CAK#D|V6eMcC~W8zdPS6-bHgV`w$JRHWnTLt3s-OwrMK zyU6UM#7C?7H+%;#Bcqx)T-_8OTk;s^hdYy2MQpCQ#h$OG>a9fP?n;coKIa#Zk`xXxvm2~&; zy{rzmVr)~P%@+Tv*l03lcCez0$vdQ-rCmZGXIc9tWcBoP_nTS84+(Ek7 zn7w4doGu?CDHH&u7@Ld=a>016*@7&y?N|T$+N9xC^|uolxe{-0V`P5Pu(vS4 zLt*hbD$HcRF!J7byhd0A?+4v=vCpp{)A8kqE6LTy!7rQhnzFOAQLSmPNHHeBNE$PQ z>8SRPE6K~URN`hcFGUYWuZ4!(#a8SCOXy^q_YqrCo4|A)CTMVe*0X!}5er$*{<)9T zl1;2+KdB&V+2#95)tGf|J~4f&YT3lT*-uJH6y6%6lU*TLsCu= zg4M(2<&o>i^`t=yTo0i?v&wA>sZ9>J1Q4d8Gee)+6ojH*#SYv+oR0*vzu-wi^tnt+!-svc#MU1?W5bt5;7ez2O)U>c??SaAUbu&VB&mWor(w4g+bUdGVCnn5X>z*TX_ib$Lh4y-%sYxwEb+ezI$S|1*NfFp~2g76W?XVX_jrpC2a6@L2K)DNVxsD}19R zkGCzhTrlSsKLR}4*^7^mSq4s1cJ}onr9EV<|oOwvBQs#$-q87Y7K97 zz&wm%yW{oGc#5pX8hhj^at0lTNQ^-k^4alg$yDZgj{IWa>Wr1EQ&ZS`&yf*q$6v{* zBSfLfj%G_!*_(eQNoeJ(zmlyo;@J?ol<;4)tE;2h)|bc?(#YNrmqPXI>oWp7dIr;ed6JYi5^+@9)I6*9P?EHEWFAoL<53T=4-ws0 zfH=Sw)eSz^E)wQ^y;+3%@sjO4x-QC7Q4q-LS<+GizAuQf$SmnqbW=WCIvtbu{A_8o zJZd9=_L(;N_r5|hG=ot(O)?g9QMXS%f1RMcv5@%k$t#8dJnSgDU(zi+(XtwK5r165!Mu}DJ==s5E@hp0UK>lWDTOlbp#+nFg%PaFD9$9>ot zpQ&CU#{>H0KA$PAmb-$Ms5VZKe#X`Z+ma(?vWqLFkw_P0!}-_6j#f%ZY>di7#JE&70r z%cbQ@RHvo46|2wZw6uA-TI;ol)!6D6G@|tSb!tup-$!4eR39{`a%rjd$Z{z-N>ZKL zl0xYVne=LDHmR79UWVrst#7TAIzsOC=l8OG>!tcpU7};B-f^&1n#W4YrJ0#^e!aI~ zy!Qs6*8wQ%f7@%&siD^yqog|j-XaiG>LzKL_FAo!OXDRPO1_hZy`G_!HAxzQ$A~mb zEAhx{mUfeR?Jv!eO!0hXtMr)!llxwmlq^kg@|9{!_fh z0r=&u(v&6DK^;AzIN)_IeIQ+aeEuA<1wfI zZ3l#1?6D4Du0)j#qQYH^B~zlp*&R|o>C#XEJ5$wcQ2@m8={98I=_y`NUp1RsFQvev zrzb|kL&*hoBG0b&iVsj}+IapVp>x-{5-3e(C%w`tz0q9O(J5ieTXaVI`}IcI=bcia zH2jMO-{2Rc{ZI%Iqz$EvgEEbMN*N`&oNUGEQneIuvhz=u$`@=(0JBa2 zQ}VlJqT8wcaylkSas!Anq`Dnl5EL%7+NJ8f*@KpiJl_iV`Lo@rQ;IbXg)=Cu=T;{O zu_UOvYr+oKw)|SJNqkijH1o88JDwJ;$J3%kp5{7foexWvopqc}WT|ILZ-B7wIa`{q z%{>d#pWUVEVptE*w0S%MlRcQ-h7N6>RtMjbGMkk?m){%d^yTSaj@5HUvzdD&Edk~X3RR9J<_&a0&) z?aN)#TF&E^o{MkoTHU$Q-CPwNdA{_s)b3;>E|9p1Rd9hcFsaU$4aW!kQdTZx`}@1t zkqe}q5Yv?xO7ozh4Fx?#*=ZL_SK-a{i-fwc^N-RL zSlY~a#dViR=Ru{&+9OTFqj-$g#A`At)e^##mdTdTqowhdxJES{p~s_WgcpJ;N8nHBSM|~i0V~0_Q6c( z#^c2a3($sD8-G1y3Shxk5A#XGsHbQJH%YTN*Z?q@&3d1Vl7SIB8@NS6+@1E?Ez*Ss zeB!xNTEJ^{eIQNMuDe_M_b9x);;@u217WA1kY=!)9g?j5^C4+hyksuB@^NW3K7I9Z z$wm{O<~$`OjX>erBhpPAgwLOs9C%c|Abkhq6u&4%^js=($6n;TlfO%4t6t)5>FKPa znErz=NlCvd_~9iG$xw~FVd)gM@93{yf(IX!CMRmlep%vv1<}t1uSlaAc}0l(p@Pa+ zq}ju2EQ+VKw_lNbz>2p1Rp}9q9ll&y&KuI`M0)G6^d-a6kG>&|)9YlgZ{Lt6>S;5} zesi#Vl4E;TJC?5EQL{T$U#UejZ)SgZQ<{qEScK{9)ifZ z-doaDK)*KsUFjSS;~mGPQat{B90XLy7X1S&tV?tKL+atvf$2?WC*PO4^z@a9qD3D{ z(M0;arz8V=`9moXFVNaP!rF&_=G>2^A}qQiA4{7gdywU%L)FRuL>fIRv257R6VjZi zPOjPxN^C4jEFdR4{S(QilTtaGbVBlhyg*h6M{%<2KbMZ7II6|r2=2v=QOw>;?&Z=mi~-wbnW=J(gj2?kfZ+sXlMUN%2*6` zBKBMg^+Ou4KLkrPi}OUBxyEI&?)9$aey(Hxk#Ks5k?*9x0E{QU1BZ*UpT84Y;Va(@ zW%86Cq;k#;e~`{1;B1496-Kp>f0U+32^_?wCO^Cd9B31MhS>tkiMw){{XuE!-jmX4 z%P=bV2t%skz^M3PDPa$bO2V9P;k#WM_=y$-EOD=*FqaRVl(yka6gQ4^Q=VJ#X{NOJ z0AU%pwpAiJ44X}t+voxkz1&L!_&r9?239eER2;1_D{ReZDTx-Ey4baZ=3t;N61o^5 zaul--4@$`ZF%!jQ5=HzO`;&NRX_VGr?~u(ML1(aw4YW>A&tlRDia1eTehWUjf8eyac{KInqi09c%kgL#LpOog?jJ*W_aBU* z6?iNjOFK|_%~)EA4?iDEapc9RjT%q8cmur?XuZA8mk&Xt8?*_!2(2FNno@lX+*(cG) zaT^iIia0mXiORG|)IZ%0sBC1%C)1SC#XhCMr=Ycs zOqxPB;=@f-=uJDSTo&Wdc#TRU@*D=E;)z&{gE%uPVPy4+6&Q?BQIY4vf?ArWsJ{pf zRuuR$Dj^i~a5Nhgf1+yqRq+U~r3v_Drzg=Ac2yExM@rd;N%R07yQb1wJl>wlX@zAb z)0N1%lW93=(e6p6s|dS0nI_*ijh-QmX=ztHt*r>n$%8dBgKm{j^~+gw2R`)876f?J zY!G%-(`HjUm-3_L(q2-kojI3+S3&5f()kE>x+7Ik>5r-O64X6EjaHK}r9N&TgK1eD z>=Pr+MYS38Xgxj(&O--Y_Ro3r1f11xr_(>MA5!T!cJ_R_L&l`nvr!q;!Vkc$Wn~$3 z!SrHZ9*Vbd-GY0DqsGDpUmj+}%FfN8cNwkfqQzN7_)!|b#?+=-IOn~HUGru2hy$Ei zQP#KsU~gv_{#3SqF&)Vc*U&NSrv>z*F+GDQ*v`H%Q9r3+&1PCiYS}ertVvxvKGtSmc|7L5e70HqkwOTc<5dm@tt z78U!jmmA~**oc%!)bohW5HG3>nfvfXgHNc-0Yv7pe=9Vnpj~X{=9Q>TZtOT()hwK* z%z__DFNbEe5I8B!&CAN=$BzbE*Hgvps6wZYsn;8Ai#NIjgQ(4-#)6u5v$D+xK8pU+ zatdqPO~Xc{VEUi|{(6+?0t4OV69c_Bi!MY{?`DBNTG{$+ii4c2Gn<;GT73!_KaWKW zt4$5q8S(iFt?agJYC(-(Pk}aJ5ruqqv0XXzi2lf7XXVmksOelxd4yf!1CLaS-~khz zqRm)BuOgFd?F!#u&g&Z(5J+3Yo?J?IjbGE=6jqzD6U^<74Xkk)Z6O=j1Iy@KOvIbZ zFqNgOZ#n%2?t#t~^gB-Qo;=z=(&`uf9M&}rB=U0}-9Rc>MLs=ABCKLHow*Y4H+s2) zM_{ER$VFRW1wV1jOY-o#*K6tw@`FYZQQB!O~OxxLP0|GFb@l~@`D81!~9?{$`dCq3rj+IQ8uB7 znp2^8qjmuLF=8&2B5Yz0tCo{zWt)m1LF(9Fis*H~ZL5_YlyL-CWpnFjGRv~jabvAM zeFFhB0XxG+mjI$(8=V9AuC!4ba_`va{am88tA#GL(B{aqvFq1jRYcj}*P=p{%_yd+ z>DODo&Fmd<41Qd&$Z*@LAtYYFxT60l&083COxN7&Se zjUlnew9a2x@8vT%3^Y5NSqAAEWh=_)GI-3f(CsW(M%%=RWwoiz*UVQ9+5o8$eAeHvW_koSI=2k-dZ2$T*d6tb@WmN%Orv@*xY<4 z^W{Hg+LDug`v2ik%mCJsQeyDDh}s^|cFIG3(tT^ocD zxn=|1lvCCY_jCMEU~08E-mfp7KE70Opcy#j5(8YU2@JHD&9~DFbb0V6J6*z-me55k zrHU3p9UdHQyV?{5g`v5q=B=WW$awqkZb}EoaXwgyQUjtcWm{_~x3D5LbOHOsPM5Qn zYiI-$Ra#5Anty&RU4z{7wcr6=Z1zUlG?6bRV*+*~nAz@)bOowDikEoIs-ux)T}UB( z1blo*NU@vis1=j(Ssgu%Vh4)tsi*1el6ty)j9qOihostob1Cd-J)J!<8pO%_LbtD} zLv4mct7gB{Lt0m}m7C};YhB1<0<~ey{z|R4`Z$L*$L}^+>&wegYC_oO%8UlH>OxtO zkWw$Q>wQ^uOlqL%SjGz)sA9C?{Jj8lyRlFQ-G|MUL)fNnOjM;qwON&f>F`@Dfp0|E_=kPJ4qppmBMSVR1%SS{=Zcc{=C zF$Mg}`k-P9ne(bb5G{oPe_j_ZnFwN2tR?o{QWR%QpM=rb{m zolP`@omWjKv5%Z`3VW~#+E2RHyqT^BOVzGwh8Be9S6k>f2|*e^Z^f(zv_c0}2(n%$ zZh&ZKC!A1Ku*2ell(1@laM3V9rAZ!IFHOe&wz!EQEe8^Y+ZX|@w~gizBPBHZ>2#`C%=>NI0=~Ml34d?%?U7c1u%@Ux8-3-LI_m zH!E!s7Eo#O!lL%LYP#{)HIy=hH8~XMylWiFHb*mj8h(|gKyd6*>Gj+Ll(~&gC*5rA zHrk2lKD3Q)#XKZ=5p~$Wd|vwB5q0e_xLTOMlQPiPNFOYYZf&a%(g()fZa;mA>vj!Y zKuQTa+(n<5SkkUv6T%~;Aljqs!XW({ls9LHE=8j(M0X>cAvH`7BL3lpFikOTYPT%f zoSnUJk+Ke{yu8is%=ATy&&Ab(o`@w^+0I5rXs%S%uH{AOVhL(jXAhmTxF?dCIk2_A zUsbass(US0_51rpVPgHI*6OS)4oeMtsD~CvjhNyddK&R){o65KP~5R7&6~JE)J<$m zSGBVRy);8w6Nx$0BsStSn!ZEWpD?eREw+d*%{iOP4~wX@ju=djUJHkKhLy1qeRLvtNJ<}_KLrgBn9-kE z59@@wTgx`|(Ux3LQH|ihVcw+>q^9-lijlifpc91DLU>Jua>9-2JRsxUK3X*%<}B_o z;S3U+#Hzj>T-8rwB+NeSrx&H`*hxr81jPXBiRL$n<}podfEvjf_P_v`#~SwT0Npri zIHrI)+18hHyvXxO0>=nNzW}7D(;u69f7C^R&O>T@NguQ-`DHo%SpI>f@ zvbj6xys=ne2{6{N${qBQQ=$vs2-_3c%TK1=NVUAZb=XtQhRqfRt8m#i6MTgge^UO*RNoOcKo-2=7wq~dI1p@G5Vp-6{Rp~5eC@bu5Ys396i6)yDC;>4D1ZAZ6xdQ{~eXYDX zuOq$(Hzu(OH#ia(^IT4AX?wuTS{{b#v0sA9@zdqBbW9+Cz7QJ5oj|#@@)S1F1czJO zUT8LzY+x^4ngb89G1Q|5fS?LL00x@l*)~8SwwJ}uZ+c&aA5e6&<9q3pZ7qp+*bR)o zaiVD0&TYIjI#e17#LL#AOVO}V=|K_!+(u{NO&~im0Tdn&%%9(ZzU4-fQ z_!>HA$2Q;#YnShRr}veH&{`QvhBmn4h1H2du~!{0w4;#w@8a_%zAi->KT{;Cr1x#( zYor5ZE*|qUys!*FyBzGSYiZJ|bbts(!52+2l8I4f@iPEfm<6L!^gqR-Q+5EKvk$KY zW)ao1k4_m~7qC=EGVKv~7_#@#l$l-la1d=-2+dGo9{7VHqtd{(?t}GN!p_}C=OnMk zd^c?fH0KpNl%@(iEB!d0%pTeYqh}qH_S4HGu$f6QIf)&7f=*$N?5F2L;;ugcH$oXZ z{{U2uO*(z7)9J&;zB@oKfIsG}>*!k&l=Q7P!ckDh4&F#j?2a4hSa$EtXy@A->2|QR z&YNIIKrY`zPbDxRpS_u0Ox9}+x6pejt;90Ror&X18F$b<=|zFO;sDpfgKFW%KwfVk zAK`o=^rIZXRU*PR%HFy|cwyH3fVhB?gTmHv9i)2^_4?yMkT5oF?gYSgZQY%8lw{}# zC=CIY`#oL8F1Q;;beVPse@rV4D1)c7v84U{QV7Jhl(6^jp{plW@hQOpR7U_89Vv|g zw&;&E+1V`5yj9~_5S+;SkZ;H2$Fo5_>-HqxhfokFAJk9p z^RQe0NR@?tbdu;F6yiXwypRibLZyNsmiY(b4=^%z@{e@dG#BdksO~T>Y>FVMyH|{g zn=Lv7*IFyrZIe~wVw{btt_>6vTv@SX;OP9d;0*LAyoy~<9~u|aWnsY zn5?jN@;)wGRCdk%^mX>jeTaoHeM`q_*B+)v2??^mgY+2)qE&yUrK7x^IAqb87h&iA znf@2t{_Kb7-KY3Fl{B~+6dyYpk*Dshmd9(3harzih@JBYJu#sa3np>Y+o%NCX^+yB z9f3|D)D6Gnu=U@G(X9=+9Gt~=;GIiKh_!E2teuk+6|?w(IZu!u7`gE=T4P&-9w4#(1E7U!KOpIK za2&-?%4fkt5iu$o&|J39(d~5L!-}Cy7RqpVnyr2us}W-BaXK68_iFwqV}~E7JWBQ$ zf8g4IzhF6)vUEI>JJ13=&_FK|PCw*zC-@oL{1@y^6tU<3LZ2H>SFMYC9cF~a_xEF6 zafi2l6uKqu4FbS}Z~3a*fFlvTZ0(cOE)~Zqu}G)H(WQ|AU8I|s{U>;O-uM%I19mp! zDR}MRuXz^!k^@iCI$F_bW?P=6D_HK+G=w2^X>_hs?Pp!j(RpL|0)$xu8_2GG`!pJW zjKZfc>-A=`Qy-usk)HS*Y$^nmJO{r+saEh;x`juE>^MTFv-^(FAi6a_4~|*Qe9zNU z$JTV36S2E?cKmrdb8PKUNvSA-IKAt67VstJG{LiU85<>{sbRsW`&OYiOls?`t#_4zaY?Xv6Z2 zSSe2IHgU?qb^#_<*X?>yt`ln=NPO_X64z$Z`!=$>Uqd%_TJr03F=6*VNoS4R7#ZO8 zS=yW6viskF;o8go{RW)my)5#kaNE82CjARy!)|yB8xYm($G7NC@ag`yVZ5$oFTPEe zwAAz7`OOI7paZ~kaViVxcO~d0bq=8uba9^0fCV5bt6-ybob8tAi;hcren&&RbUj)T z3}O>=90LPf$NG;^qg2(&_8+59OY7pahCJtbkW@FnL)((-9A;$$zW~AH20+~32XShA z7yiByR`o8Zt4@3JU8uaU6yJT1W{up`2@@Kj3R8~L3`53soudRy-(*F_zOKLH$;>Y zZP)vB7v0f_QFi*>4ro%IHi5Qyt}ZB0=4k_h!gw=`jjG5d*eGtbiHoSZAZiBVS-ZYZ z<$<;%%GZMyu#g1P6a|}5fN3v+=o9%6KICM;=Y%)pM_#|IAzt7>f#9OqxPhfp4Ta+6 zUiRY0Gk$b~v_ruv&&k;K>HtMtAwAJ#gKN%2;an&FZ2OvT8I$*7s z8Kct5ks*q*bvkcHL7`rf42-WK33A$2hYtyA}cbhJC8#~$dPvIKc#D4k|7ScL) z=4bR`$=Ajveg>c0izmQ`Dn6s5Si|RZIjLfod`{b^*9CQAZEcOSSRH(&PMh=vt&~WB zZT*VYp!U6Afm4TA(=T)>Yxo*$%*E0qc?x9uGD*&1|M(iK+0Uka11F1@`M-f*-=SUb z4fc5fNAbUCg}gpu9$=3h#BLl;d;W{AmV#~U(M@uiw&+{>GnFH4N+-+to<;%wZQs)j ztd67K!?I{)BYvRGJ6eEEe`_mF;CDNqpE{An`W{x&qU-!lKC6v<5ebV<7<*C7ysmb) zgdltyx!S!J4I~H{r>EomDjZK?4*?sM$beu)dUMb4{~1+193P;6${XJxb-(5V#<$ z>7d#aSzbKZhvRG>xL!TFvj+D*u<<`&P1tMUS}pv6PG;B2@;E8l#*W+MSu(1d`MVVM zfh^CEta>q6;tLG&#B^uKoWC(>;t%f3tZcI^+TsYRj;yB5Jz32Q(-+|q9`>j~ zHskc=rv~{H0%hsj5ppAxr41tiBF;mOlx<1d+OpdnA->~SSmeiv0*B93#y%J+H^UAo z8YLsHt(rZ4id>Rj3OeMGWZdgk3=f7s2+q>cX6eI$TNt&la`OBvYqVSsec|lU@)eNP zbH>OelEcm2Kqr4M81nc*pNQ1XnH}*koCQMF}m1|lVsD5dQ=m{ z3*n4pr^AQyt1vW?<^*L_O7s-ugHc(Jw9Z*K#ZxF;ha_(Ofe*?9lcox}czcaV#>F{A z7{WP3Mnt}bkrN8Yw73eaCJKbDju-^yo-8*{2zLJpgW5}zGBN_?b?wU@_x?yI%moM0!wqumLH`JZRWii z0%r>5$oG$|Z)@h)2;(#g_XN$Azak~~rOHnb+SP7iFYcmKwYSq`6K-2^<6y$5dGbE! z4Y$mbKPR(&-A&l*4Es0opb`E0)#ikU*RI_&U%s45Rc*|X0@`gc%Qnc18_aT+9PT#f zv8q|}97zeXJIwNYS&f&>ls(<%eBq4IsurTF_+b8>Dc4cxUFD19uSvCL$&rsptNcJ= zz#qWT2F$br8Te>KE~_2!A7c847wW>#)s0Qnq9yVta)hU{m&#$u6-Q(wjz~ZI$5MG~ zile((KhD&GILBHw%R?FQ|&b3ld! zL7>~RRe1fdc+&g2xe*otrN()x$akWOE-R2t?`!9+w4s%Rb(AFhE=I);gDl}d>}IAF z@&d3<`wBUEhnq_T7)e=P)rSM^P7VUka(@l3L*`k2(kn|`-WM-ji(X+Bx(Afh^gd_z zKxzS=@obcX&?5#Cx6oh&4$sDYmM{lF#D4bS3b_ufcJ)fRH$k|`+8?0y_H<7dp+-9=y&rxnRF zpc|x>$y3>#MRLyKwr;bzFYW~4=GgXb1V8YI<`BQ^tp{&^sdNekX2F7NaS zpLxRKL%iEsyhO0auN^pcrds8!*#IaJEuZkc0EI0sZq(Y@Ayfg=I&PJJ!9m&gY#32D z`^6?_?yv%N(C}dlBLT`0X}@34jE$pu4dz0Z&VFtiZ_u+sZ50I-DA0ww$d<>m5bh#h ziF}-(M1C9cgI2!ZzX?s2p-87OQKK4w40B1gf__9c?vk`8UUTO}d*Y?;oNz)lE%kST zdj|Fv%So#`@mg13qj;lp&{BM#pk9ay8zqyUId;$Pz;t+#BM5vpid!ePvHntd z35?mhOXUC;;bjnq725hTIf?JHZCxk#u#M$%DP}5ly^NEW?Cte(6e`W@>*Nv?URy3F zPps}%THT7h8z@kmF1UD}D3`ZQv4;@qgFPUhI0D)vUKCZx^I(RzR>*T?eA3Q#SIBlW zT2(72YhP8!mr^(-&Zv^>CwFu!4$yT_HKlheQP(i{(sv_^x)He<#%acf;jDrWzkqG3 zkq^j~-O$v3u93^epliM$5WysxUJQxO>CDgzqSZTNf3B5J*%6Ja26e!E*pG|Gj7mL{ zob>cuhpxHSbK>g)X$X16xodh~2Ui~(2FoJhcu@(81`SwIX?>yuVlQ546N=hZ8}}WG zD(ggEH^4+e6$*4p7TLyl7L+XVo|XhLbz{FD1QBMpZj|$&zkRS#UimBD!q(QweR%O$ zootlCE$m2&JaccoJfA(hNuI^l)XQa(r-eCA(kynkUY;#Cb|V1wWRpCDeOr%)yV=xD z@~x1Pk8F~yv^%aoviS{is=TfnW&>`FnJ!dJt+hdZjR!jyY?hak2L71CVw*vnmd$d5 zCO3oX##dV{<+xD@R{`J>Hq;^eP6@W~QwoUhU=Mf5b787Sw#jdk?OL^0zMn!v9utsvqV&Rm+-S18 zK-IXzkURVkTBYZNmW0r%L6}l&*@P~vni{sL3!HsB+tDTO#$!}a-Y}&G+G_$1Y~|wq z;(FE*lvhZ#ZdQ0DkhbAMdE_GQ!LAjD>M`7*(Wct|XBbUu-AWJpE+}tH3bp*s7>|ay z`WTXzB>8{mwT9PUS1jTU8H+vVx(WDoS6D0^bNyb_O}w_`94RveXGK*ViP zIe!MWO`#GCs|t6T4UOE}!ggL~n8GeRC{JeTz4FgVuHWgEE$ajSu(5$Ya32KH^~vX^ zhFTPVi{fZeTrG;XrP-_^USX)+HEw3vC#SOBeu$4=c1yq9AZ>s#a-Crwvk%B)Snhzl zWOT2H)4|5L*ilXzCA_uRhGORp$XV0ZxDif;b1=A|Ef1j+W(C!O-HZ(O%?*&2`>#eb zUk}K)CRO|ok}*dIPm|l&m8Ze5u4kql^8QJY7Ea9DI57(gql~?=L*6yU-NGBq$Ie45 z+jhFVdWO3No7dP`kG6mSJ%Jm#W|J$AZ$HtgtXAHR!rjUNug90Sf2X@v~bmmHSr>j-}n49ohh~P zIz#goU`>CJ&zCw|#fs9#TqAEnxDj(-3zP-0T?w7i%Km(~7)&JPTiB&ii_#to1pz1o#GpdawP2X2&49Z|ta+RPri4s5iCVLx->O>%Qu zCFg29&Ii+5>oVaIW}FwmmGV3sOK>6f(yfNn(Syak?9`jVV?Mq~9-p>$7;OLF-`23v zH_4;fH8;xz%XtHN90H|Wj00F0n#vyDIy;X^}LXup4i>zSnJaY?thfm)kk7pxpmHEbua;tm`X8-TE%C}9c7C2Gt z;xW{9Da*MXAr%kYCP%QVf%KMB5-hftvD@W~CMOtlTB5v+t++$JHYxr0gv5zE`OxJS*(ZAJ(a{x-u{sF(8ySDZKEvE5PbFcYt$%=Ii3HJrD9PHy9O3`hP79}$AL zj>u_P6RVEMmm|lo2x0#?A|C{CU-G>C9+p%g6eob~8(DtKm%TEKA z-N(TDA+1k+PkwJgFGABelW+G~DzHYhMaSjSWi)p8hjKX{KYu7APFgGf2rflr_kAp{ zl1p8VDpHl=y`RWy@$&Rfu@)OYf$*}jt3Hue;lea_pau-(^G}2|lX^lt zYEMA3w6g6dWFG!<^$DmPi0j^Ln2iVd6#BB2t^QPSw)#(DT#0tC#$(oJAb9vhK9e)? z@O=iQ(8@0QOx}pc2cOBEcvOEb7XaElpUWyS@R9YhlV6~yS1b4uHhWSpuE7kM;1mN_ z;QLHq3^?5X71&Cz_UKozd12MR^R;{`?gC(Q|1CG-zIIG#BBmai2|M@SV1T{so_|B= z_Oj>y4VAQ)-S!`O(X?K1f1L*rY?d}vK`vdjY)689^B;M)jD~vIz;|%2_KF>O_RFnw z^n7?)JUk+=5`PVaFJM}iB`!P1ZKrMGPU~Lw)^~D_)T^@b4#P}?sV0c6+pO>9b!ch( z_i`hDb7!7mh5_M0NdC9oFoTWzL0%p&pU$@YAV0&A0RS?8l>bJ0_x=}Cgz5h;Z2ewV z_>(+!R4*uYy9#7%{z=Z9-HRyWDjcR!voLs9Bp3v$DsZ5n9dXLN+6_O+3ppEp@n?Cx z6b-U(>J3RO=NAZ}D0BWI`!Ekjf03_3)83QvpYa$=493gX8}jtz+{m%a`yBUTtR<-h2dFf_6JuQrj54+S6AVScAxkQ zBJGux1{{gTO{#gQX=5#UhWT@B!2(MaA2qlGZhppJ!vt4b+W8?Q{Lh+=U6*HALh7_v z^9(m3l2RM6aOiNpw$QMWBWH`%;K$;_!- z&kooPY3vHSAs5X(XE$_7Db-%fdVjVn6snGRJ)!vAAn3We#&D6r?p3P2EcGpUwkFkr z5Mdgt8x3nffwylo__z?6QEza9rUvQ_3nZNH1d_4B8w_`$tg+E>C7ET#%?krX+zt}z z@ur}q&+Es9Rh~TD2Rvc3VE}VD#Ls4H&ulha!7X3M7Q=103tk)RG`z(z{fW!)J+jB$ z2LEXEU*$K<8v`6{=!KeoS+C&>q|fLxl;Lrt&oBqwf7WM^BvPb(Ibir08xGp5ryCr6 ze`MtuhWC;-{+_H>&NSGe9SodlD8l2>GYw72bwWEBl&}d~H}@>VO1fccX z5Rz+HGGpU!RgF}xz|X^JCie4g!vgl+Zo_1Z=3l!Fxl`)?w=P?8u3`Cv`r$f^y_MZ_ zH~bzKpKEX#2hAFAWG^^$zVPIV3{FiU_yDK0kJBW6H-%xUxo@y~JdlI@8xF0a(0%R4L?yNC|Tu{T7F=|V!>GU@wcoTHruG}ZU1Winl$FGcL7 zo<&6IdI5Wc!G41R{s`{jMiB$iF_Rwv9?hZOqx?MjS;SM-mAQn;NQQna@pCjqHywVz zrRbZ3!_@5{=9}oC0|}ir+x(}ujky;mhr7*ku-80$ zGw7XOKWp5d-6)6U(P>-`-uD|H`i)z7X7Jp;={LMzbCo__d#MVd$G!^j)=HCZ8vbsp zm?%~$QK}-+eP1O+9X?D|oAkaoh*5%j%2ZBN*sqxMu~sEfkN;EEC3@wv)0Kw5HjKm| zv{?D7L)3+@?guqCE&5EUr!tBk$!VfO{dBFRPJE(=j6|<}FinO5yLXuGdBD^!gnG;t z%$g$pYU8CZe1>mxXyKb9gx;>$H3o=z4)d%vhOQD)XI&`5BS}GT@KZ|Mlnn}0$bt08KbL}9kB&<+_>6xAq{x51MR)MO9 zw$?y?U`wK(t8;@I8kM(}f+bTI8uqL~IXY~54{mLauAAPy1r0K<(Fg~QQ$+bN7=3Pf zFM}1|#y)}s>*IdSIgN78KjqU<+Qt!0ZR3#$9iIP4nF4Fw_G#wn#wPsm(q<|^KTaLd4L zl6-^$@E}y^IvFKr%Y%+x4?~GR?GjV6KiO+oOQ43?uBm1A3rS#uN+37zFh~%CYa_># RR~a79B-=M%mc1W8e*@BE`;7nq delta 117 zcmcbARb<_9kqtEp&8HRGPb)A2F%u9oZ$GWTa+gooF)&Rh-O15W+es(f(J@rV*)eju zrxA-9W6<;hBNip*P<`j=%Z*slm@J*92O6`O3OhPFdg^#OI=kt(J34ynq&m6>Z0|Q_ S31(tVb~XmGKU%W9`v3qX6eXVk diff --git a/netbox/project-static/src/select/classes/dynamicParamsMap.ts b/netbox/project-static/src/select/classes/dynamicParamsMap.ts new file mode 100644 index 000000000..c47535c9f --- /dev/null +++ b/netbox/project-static/src/select/classes/dynamicParamsMap.ts @@ -0,0 +1,76 @@ +import { isTruthy } from '../../util'; +import { isDataDynamicParams } from '../../select_old/api/types'; + +import type { QueryParam } from '../../select_old/api/types'; + +/** + * Extension of built-in `Map` to add convenience functions. + */ +export class DynamicParamsMap extends Map { + /** + * Get the query parameter key based on field name. + * + * @param fieldName Related field name. + * @returns `queryParam` key. + */ + public queryParam(fieldName: string): Nullable { + const value = this.get(fieldName); + if (typeof value !== 'undefined') { + return value.queryParam; + } + return null; + } + + /** + * Get the query parameter value based on field name. + * + * @param fieldName Related field name. + * @returns `queryValue` value, or an empty array if there is no corresponding Map entry. + */ + public queryValue(fieldName: string): QueryParam['queryValue'] { + const value = this.get(fieldName); + if (typeof value !== 'undefined') { + return value.queryValue; + } + return []; + } + + /** + * Update the value of a field when the value changes. + * + * @param fieldName Related field name. + * @param queryValue New value. + * @returns `true` if the update was successful, `false` if there was no corresponding Map entry. + */ + public updateValue(fieldName: string, queryValue: QueryParam['queryValue']): boolean { + const current = this.get(fieldName); + if (isTruthy(current)) { + const { queryParam } = current; + this.set(fieldName, { queryParam, queryValue }); + return true; + } + return false; + } + + /** + * Populate the underlying map based on the JSON passed in the `data-dynamic-params` attribute. + * + * @param json Raw JSON string from `data-dynamic-params` attribute. + */ + public addFromJson(json: string | null | undefined): void { + if (isTruthy(json)) { + const deserialized = JSON.parse(json); + // Ensure the value is the data structure we expect. + if (isDataDynamicParams(deserialized)) { + for (const { queryParam, fieldName } of deserialized) { + // Populate the underlying map with the initial data. + this.set(fieldName, { queryParam, queryValue: [] }); + } + } else { + throw new Error( + `Data from 'data-dynamic-params' attribute is improperly formatted: '${json}'`, + ); + } + } + } +} diff --git a/netbox/project-static/src/select/classes/dynamicTomSelect.ts b/netbox/project-static/src/select/classes/dynamicTomSelect.ts index 370eba60d..6b4667684 100644 --- a/netbox/project-static/src/select/classes/dynamicTomSelect.ts +++ b/netbox/project-static/src/select/classes/dynamicTomSelect.ts @@ -3,6 +3,7 @@ import { addClasses } from 'tom-select/src/vanilla' import queryString from 'query-string'; import TomSelect from 'tom-select'; import type { Stringifiable } from 'query-string'; +import { DynamicParamsMap } from './dynamicParamsMap'; // Transitional import { QueryFilter } from '../../select_old/api/types' @@ -16,6 +17,7 @@ export class DynamicTomSelect extends TomSelect { */ private readonly queryParams: QueryFilter = new Map(); private readonly staticParams: QueryFilter = new Map(); + private readonly dynamicParams: DynamicParamsMap = new DynamicParamsMap(); /** * Overrides @@ -32,6 +34,15 @@ export class DynamicTomSelect extends TomSelect { for (const [key, value] of this.staticParams.entries()) { this.queryParams.set(key, value); } + + // Populate dynamic query parameters + this.getDynamicParams(); + for (const filter of this.dynamicParams.keys()) { + this.updateQueryParams(filter); + } + + // Add dependency event listeners. + this.addEventListeners(); } load(value: string) { @@ -40,9 +51,7 @@ export class DynamicTomSelect extends TomSelect { // Automatically clear any cached options. (Only options included // in the API response should be present.) - if (value) { - self.clearOptions(); - } + self.clearOptions(); addClasses(self.wrapper, self.settings.loadingClass); self.loading++; @@ -114,4 +123,114 @@ export class DynamicTomSelect extends TomSelect { } } + // Determine if this instances' options should be filtered by the value of another select + // element. Looks for the DOM attribute `data-dynamic-params`, the value of which is a JSON + // array of objects containing information about how to handle the related field. + private getDynamicParams(): void { + const serialized = this.input.getAttribute('data-dynamic-params'); + try { + this.dynamicParams.addFromJson(serialized); + } catch (err) { + console.group(`Unable to determine dynamic query parameters for select field '${this.name}'`); + console.warn(err); + console.groupEnd(); + } + } + + // Update an element's API URL based on the value of another element on which this element + // relies. + private updateQueryParams(fieldName: string): void { + // Find the element dependency. + const element = document.querySelector(`[name="${fieldName}"]`); + if (element !== null) { + // Initialize the element value as an array, in case there are multiple values. + let elementValue = [] as Stringifiable[]; + + if (element.multiple) { + // If this is a multi-select (form filters, tags, etc.), use all selected options as the value. + elementValue = Array.from(element.options) + .filter(o => o.selected) + .map(o => o.value); + } else if (element.value !== '') { + // If this is single-select (most fields), use the element's value. This seemingly + // redundant/verbose check is mainly for performance, so we're not running the above three + // functions (`Array.from()`, `Array.filter()`, `Array.map()`) every time every select + // field's value changes. + elementValue = [element.value]; + } + + if (elementValue.length > 0) { + // If the field has a value, add it to the map. + this.dynamicParams.updateValue(fieldName, elementValue); + // Get the updated value. + const current = this.dynamicParams.get(fieldName); + + if (typeof current !== 'undefined') { + const { queryParam, queryValue } = current; + let value = [] as Stringifiable[]; + + if (this.staticParams.has(queryParam)) { + // If the field is defined in `staticParams`, we should merge the dynamic value with + // the static value. + const staticValue = this.staticParams.get(queryParam); + if (typeof staticValue !== 'undefined') { + value = [...staticValue, ...queryValue]; + } + } else { + // If the field is _not_ defined in `staticParams`, we should replace the current value + // with the new dynamic value. + value = queryValue; + } + if (value.length > 0) { + this.queryParams.set(queryParam, value); + } else { + this.queryParams.delete(queryParam); + } + } + } else { + // Otherwise, delete it (we don't want to send an empty query like `?site_id=`) + const queryParam = this.dynamicParams.queryParam(fieldName); + if (queryParam !== null) { + this.queryParams.delete(queryParam); + } + } + } + } + + /** + * Add event listeners to this element and its dependencies so that when dependencies change + * this element's options are updated. + */ + private addEventListeners(): void { + + // Create a unique iterator of all possible form fields which, when changed, should cause this + // element to update its API query. + // const dependencies = new Set([...this.dynamicParams.keys(), ...this.pathValues.keys()]); + const dependencies = this.dynamicParams.keys(); + + for (const dep of dependencies) { + const filterElement = document.querySelector(`[name="${dep}"]`); + if (filterElement !== null) { + // Subscribe to dependency changes. + filterElement.addEventListener('change', event => this.handleEvent(event)); + } + // Subscribe to changes dispatched by this state manager. + this.input.addEventListener(`netbox.select.onload.${dep}`, event => this.handleEvent(event)); + } + } + + // Event handler to be dispatched any time a dependency's value changes. For example, when the + // value of `tenant_group` changes, `handleEvent` is called to get the current value of + // `tenant_group` and update the query parameters and API query URL for the `tenant` field. + private handleEvent(event: Event): void { + const target = event.target as HTMLSelectElement; + // Update the element's URL after any changes to a dependency. + this.updateQueryParams(target.name); + // this.updatePathValues(target.name); + // this.updateQueryUrl(); + + // Load new data. + this.load(this.lastValue); + } + }