this is the way I am receiving an object from the DB
{
BET: 57630343,
CUSTOMER: 181645,
SPORT: 'MLB',
'XX_FILL OPEN': '<button class="btn btn-xs" ng-click="fillOpen(57630343)">Fill Open</button>',
XX_VIEW: '<select>\r\n <option value="volvo" label="Volvo">Volvo</option>\r\n <option value="saab" label="Saab">Saab</option>\r\n <option value="mercedes" label="Mercedes">Mercedes</option>\r\n <option value="audi" label="Audi">Audi</option>\r\n</select>',
XX_CANCEL: '<input type="checkbox" name="sports" value="soccer" onchange="fillOpen(57630343)"/>'
}
as you can see the props starting with index of XX are HTML elements. I am taking those elements in the front-end with JavaScript and injecting them into the DOM.
This is the first time I am doing this. I am used to take an XML and send it to the front-end as a JSON so I render it.
Is there something wrong with the way we are doing it now? is there any unsafe technique here? would be easier for hackers to break into my system?
ditto on Sebas comment which should really be the answer. Security should always be handled on the server side which means this practice shouldn't make things worse.
Additionally, storing html like this is going to be a nightmare to maintain. For instance, if for some reason the 'BET' id needs to change, you will need to regenerate all of the html for that row. See data normalization for more information on why this can cause issues.
Related
Consider this HTML page using the HTML Javascript package
<html>
<head>
<script src="https://unpkg.com/htmx.org#1.8.0" integrity="sha384-cZuAZ+ZbwkNRnrKi05G/fjBX+azI9DNOkNYysZ0I/X5ZFgsmMiBXgDZof30F5ofc" crossorigin="anonymous"></script>
<title>Test</title>
</head>
<body>
<h1>Prova</h1>
<select name="brand" hx-get="/models" hx-target="#models" hx-trigger="change">
<option value='325i'>325i</option>
<option value='325ix'>325ix</option>
<option value='X5'>X5</option>
</select>
<select name="model" id="models" hx-get="/models2" hx-target="#numbers" hx-trigger="change">
</select>
<select name="number" id="numbers">
</select>
</body>
</html>
Consider that endpoints models and models2 return a bunch of options depending on the value of the select being changed.
The response is something like:
<option value='325i'>325i</option>
<option value='325ix'>325ix</option>
<option value='X5'>X5</option>
I wonder how I can make that whenever I change the select brand, that triggers the HTMX GET Request associated with the model select, which itself will populate the numbers select.
What I see happening, right now, is that the change to the brand dropdown triggers the population of the model dropdown.
I would expect the same to happen for the number dropdown as a consequence of the model dropdown value being changed but that is not happening. Can you elucidate me why that is not happening? And in that case how I can fix that using standard HTMX?
Swapping the new content into the models element does not actually trigger the change event on the models element. You'd need to define an additional trigger event to get the models element to issue its hx-get request when the brand changes and therefore the models options are updated. You could do this purely on the client side in HTMX with a delay so that your models selected value is sent. Or you could have a combination of client custom trigger event and a HX-Response Header sent to the client to trigger that event.
Here is an example of a client event. Added a long 3 second delay to illustrate how the trigger from brand needs to wait until the swap has finished. If you just had the from:brand trigger without delay, it would fire instantaneously (before the models content was populated) so that post would not include the preselected model option. Essentially a race condition. Also went ahead and included the brands element in the models2 request. Maybe you didn't want models2 server side logic have to worry about the brand... but if two different brands had the same model name, then you may not know which set of numbers are supposed to be returned... For the following to work correctly, please add id='brand' to your brand select element.
<select name="model" id="models" hx-get="/models2"
hx-target="#numbers" hx-include="#brand"
hx-trigger="change, change from:#brand delay:3s">
</select>
The other way to do this would be to add a custom event into the model hx-trigger and then trigger that client event from the server in a Response Header. Added a short 5 millisecond delay so that HTMX has time to finish the swap before making the call to models2 .. Again, so that the preselected model is included in the request to models2.
Clientside:
<select name="model" id="models" hx-get="?handler=models2"
hx-target="#numbers" hx-include="#brand"
hx-trigger="change, get-numbers from:body delay:5ms">
</select>
Server Side ASP.NET here (your server may need different syntax for adding Response Header)
Response.Headers.Add("HX-Trigger", "get-numbers");
Was requested by maintainer to repost here
Issue
In https://htmx.org/examples/value-select/
I can tell that the make is directly in the html and when it changes, the hx-get is called to fetch a new list of models.
What if I want to have both the make and the model all rely on ajax?
meaning to say
<select name="makes" id="makes" hx-get="/makes" hx-trigger="load">
<option value="none">original</option>
</select>
<select name="models" id="models">
<option value="none">original</option>
</select>
i like to be able to fetch from /makes on load to get the list of makes option
and then somehow I can also fill up the dependent models as well.
I don't mind doing it as two requests. The reason is that in my situation the makes are also dependent on a 3rd party API
I hope I understand what you want, but something like this should work:
<select name="makes" id="makes" hx-get="/makes" hx-trigger="load">
<option value="none">original</option>
</select>
<select name="models" id="models"
hx-get="/models"
hx-trigger="changed from:#makes"
hx-include="#makes">
<option value="none">original</option>
</select>
So you add a trigger to the second drop down that listens for changed events on the #makes drop down and then fires up a request to the /models URL, including the value of the #makes drop down so you know what models to return.
Does that seem like what you want?
I have a variety of HTML select elements inside of Nuxt.js. I'm also using Vuelidate for validation and this is working as expected. This is a typical select box in my form:
<select
id="location"
name="location"
v-model="form.location"
#blur="$v.form.location.$touch()"
:class="{error: appendErrorClass($v.form.location)}"
>
<option :value="null" hidden>Choose...</option>
<option
v-for="(item, index) in $store.state.quotes.data.practiceStates"
:key="index"
:value="item.data">
{{item.display}}
</option>
</select>
Before selecting any of the options, I'm noticing the following on all select fields.
I've tried removing any Vue magic on a test select field to see if the same results happen.
<select id="location1" name="location1">
<option value="" hidden>Choose...</option>
<option value="one">one</option>
<option value="two">two</option>
<option value="three">three</option>
</select>
Still seeing valid: true. Is there anything I'm overlooking that would cause the validity to default to true? Thanks in advance for any help or guidance on this issue.
UPDATE For Clarification:
Vuelidate validation works just fine. The issue I'm dealing with is the select field property Validity.validate. I only mention Vuelidate to give full context.
HTML Select is a sort of "strange" form element in that validity is typically checking to see if there's a readable value. Since a select always has something picked, it validates...
This is different from say a telephone input that has a specific pattern required to be valid.
I haven't used Vuelidate specifically, but I read the docs as saying, if you left the v-model="form.location" there's a good chance it's simply validating that a value exists so Any selcted item would qualify.
In my original post, I referenced the dynamic style based on the vuelidate library: :class="{error: appendErrorClass($v.form.location)}"
#PierreSaid responded to this post and later deleted his/her reply. Turns out, his response was helpful in pointing me to some Vuelidate attributes that were able to assist in a workaround for my issue. Thank you, PierreSaid.
I have since updated that dynamic class to be a mixin that looks like this:
export default {
methods: {
appendErrorAndValidityClass(field) {
return {
error: field.$error,
invalid: field.$invalid,
};
}
}
};
After importing the mixin into the Vue partial, my select box looks like this:
<select
id="location"
name="location"
v-model="form.location"
#blur="$v.form.location.$touch()"
:class="appendErrorAndValidityClass($v.form.location)"
>
This appends a class of invalid when the select field has not been updated. It also updates the error style accordingly. Now, I can assign styles for when the select field has an invalid class. This solves the overall issue for me. Thanks for your help PierreSaid and Bryce.
I am trying to generate a view that has collapsing panels in it. I need each panel to have a unique ID. I have successfully done it with the code below. but was warned in a different post that using #Html.Raw() is bad practice.
What is my alternative?
#Html.Raw("<div id=\"collapse")#Html.DisplayFor(modelitem => item.NAME)#Html.Raw("\" class=\"panel-collapse collapse collapse\" role=\"tabpanel\" aria-labelledby=\"heading")#Html.DisplayFor(modelitem => item.NAME)#Html.Raw("\">")
You need to understand why Html.Raw is a so-called "bad practice." If it were universally bad and should never be used then it wouldn't have been created in the first place. It's bad when it is used to write non-sanitized content to the browser because it leaves you vulnerable to an XSS attack.
Having that understanding, we can look at what you're doing and see that you are not writing out any user-provided data in your calls to Html.Raw so in this case it is probably an acceptable use.
Having said that, it seems like you could simplify things by passing a collection of divs to create in your model and just loop over them, something like the following, which may require some tweaking to get it just right.
#foreach(var panelName in model.PanelNames)
{
<div id="collapse#panelName
class="panel-collapse collapse collapse"
role="tabpanel"
aria-labelledby="heading#panelName">
}
You can simplify your code by combining text, markup, and razor Code.
In your case, use HTML with inline Razor expression :
<div id="#("collapse" + Html.DisplayFor(modelitem => item.NAME))" class="panel-collapse collapse collapse" role="tabpanel" aria-labelledby="#("heading" + Html.DisplayFor(modelitem => item.NAME))"></div>
More information about Razor syntax.
I'm trying to crawl a website using Scrapy.
I need to query the list of all existing items of a board-like function on my target site.
The problem is that it only searches within a target year, designated with a HTML tag option.
So I need to find a way to changed to location "selected" attribute within the s.
I think I'm not really doing my job at describing my troubles, so I'll append a simplified HTML code of the site:
<select name="Search_FIS_YEAR" id="Search_FIS_YEAR" title="fiscal_year">
<option value="2014" selected>2014</option>
<option value="2013">2013</option>
<option value="2012">2012</option>
...
<option value="2007">2011</option>
</select>
So the default value of my target website is 2014, but I want to programmatically change its value to 2013, 2012, etc.
The search query is sent through a large that makes a POST request method to the server.
Fortunately I found a way to send the query using FormRequest.from_response, but I wasn't really successful in modifying the above part of the code.
I already knew the answer.
All I did was to just change the value of option within the form data:
yield FormRequest.from_response(
response,
formname=NAME_OF_FORM_WRAPPING_SELECT_HTML_ELEMENT
formdata={
'Search_FIS_YEAR': '2013', # or any other year value
}
callback=self.other_parse_function
)
This did all the tricks for me.