JAVASCRIPT removeRow() function - removechild

i would like to know the syntax for removing a row which was added by appendchild.
There is also a removechild, but I am not sure how to operate.
<input type="button" id='submitlink' value="ADD_AGENDA" onClick="generateRowAgenda()" name="AGENDA"/>
<input type="button" id='submitlink' value="" onClick="removeRow()" name="AGENDA"/>
<script language="">
function generateRowAgenda() {
var temp ="<p><input type='text' class='textinputagenda' name='MM_AGENDA[]'></p>";
var newdiv = document.createElement('AGENDA');
newdiv.innerHTML = temp;
var yourDiv = document.getElementById('AGENDA');
yourDiv.appendChild(newdiv);
}
function removeRow(){
yourDiv.appendChild.deleteRow(newdiv);
}
</script>
<br>
<div id="AGENDA" align="center"></div>

That would be:
function removeRow(element){
element.parentNode.removeChild(element);
}
removeRow(newDiv);
That is, the removeChild method actually belongs to the element's parent, so you need to reference the parent first (by using parentNode) and then call the method removeChild over the newDiv element.
Also, you have two elements with the same id: submitlink. And that is not good.
If you rename your element, you could add a listener that call the removeRow function.
<input type="button" id='doremove' value="" onClick="removeRow()" name="AGENDA"/>
(Now the id is doremove)
Now do something like this to make the removeRow function to be executed on click:
document.getElementById('doremove').addEventListener('click', function(e) {
removeRow(newDiv);
});
Here is an example on jsfiddle: http://jsfiddle.net/5TmQC/
You'll notice that remove only works with one agenda item. You want to work with several agendas?
Try this then: http://jsfiddle.net/5TmQC/1/
Almost same code, but this one can delete several, in order by using pop()

Related

handle errors with HTMX

<form
class="" id="form" hx-post="/add/" hx-swap="afterbegin" hx-target="#big_list" hx-trigger="submit">
<input type="text" name="langue1" >
<input type="text" name="langue2">
<div id="errors"></div>
<button type="submit">GO</button>
</form>
<div id="big_list">
.....
</div>
I have a big list in #big_list, and I want my #form appends only one row when submitted.
How with htmx, can I handle errors and show message in #errors ?
I created this solution so you can use hx-target-error = to define which HTML will be displayed after a failed request
document.body.addEventListener('htmx:afterRequest', function (evt) {
const targetError = evt.target.attributes.getNamedItem('hx-target-error')
if (evt.detail.failed && targetError) {
document.getElementById(targetError.value).style.display = "inline";
}
});
document.body.addEventListener('htmx:beforeRequest', function (evt) {
const targetError = evt.target.attributes.getNamedItem('hx-target-error')
if (targetError) {
document.getElementById(targetError.value).style.display = "none";
}
});
If your code raises the errors (validation?), you can change target and swap behavior with response headers.
Response.Headers.Add("HX-Retarget", "#errors");
Response.Headers.Add("HX-Reswap", "innerHTML");
If you want to return a status other than 200, you have to tell htmx to accept it.
4xx would normally not do a swap in htmx. In case of validation errors you could use 422.
document.body.addEventListener('htmx:beforeOnLoad', function (evt) {
if (evt.detail.xhr.status === 422) {
evt.detail.shouldSwap = true;
evt.detail.isError = false;
}
});
It works in htmx 1.8.
If you want to remove the error message on then next sucessfull request, you could use hx-swap-oob. Out of band elements must be in the top level of the response.
So the response could look like this:
<div>
your new row data...
</div>
<div id="errors" hx-swap-oob="true"></div>
Update
You can now use the new powerful extension multi-swap to swap multiple elements arbitrarily placed and nested in the DOM tree.
See https://htmx.org/extensions/multi-swap/
Although it doesn't follow REST principles, you might consider using an swap-oob to report your error back to your user. For example, your request might return a (slightly misleading) status 200, but include content like this:
<div id="errors" hx-swap-oob="true">
There was an error processing your request...
</div>
If it's important to follow REST more precisely, then you'll want to listen to the htmx:responseError event, as mentioned by #guettli in his previous answer.

vue v-model does not seem to be working in modal

I am pretty new to vue, and am trying to use it in a bootstrap modal. The relevant div in the modal is as follows.
<div class="form-group row">
<label for="priceQCField" class="col-sm-2 col-form-label">Price<span class="red"> *</span></label>
<input type="number" step="0.01" class="form-control col-sm-4" id="priceQCField" name="priceQCField" min="0" v-model="job.price">
</div>
I read some other questions about vue returning strings rather than numbers, so I have converted the job.price to a number inside my method to call the modal
showPriceJob: function (job) {
this.job = job;
this.job.price = parseFloat(this.job.price);
$('#mdlPriceJob').modal('show');
},
However, job.price refuses to appear in the input field either as a string or a number. I know it is available to the modal as I can see it using <span>{{job.price}}</span>.
Can anyone advise me please?
Additional - I think it is a display issue - if I change the input field, the entry in the <span> changes
2nd update - initial table
<tr class="light-grey" v-for="job in jobs" v-on:click="viewJob(job)">
<td>{{job.id}}</td>
<td>{{job.customerName}}</td>
<td>{{job.description}}</td>
<td v-bind:class="job.dueDate | dateColour">{{job.dueDate | dateOnly}}</td>
<td>£{{job.price}} {{job.isEstimate | priceEstimated}}</td>
<td>{{job.delivery}}</td>
</tr>
Upd.
According to your comments to my answer you are using v-for and you can't use this.job within your method. You should give us more code to see the whole picture.
Upd.2
You have showed more code but I didn't see any v-for so I am confused. You can try to use something like this if job is a property of appData.jobs:
showPriceJob: function (job) {
this.appData.jobs.job = Object.assign({}, job);
this.appData.jobs.job = parseFloat(this.appData.jobs.job.price);
$('#mdlPriceJob').modal('show');
},
But I'm not sure about this because I don't see where job is declared.
Upd.3
Oh! Wait! You have this code:
data: appData.jobs, but data should be in this format:
data: function(){
return {
appData: {
jobs: [],
},
}
},
Or show me what is your appData.jobs variable is.

RIOT.JS: Showing an element depending on input value

I would like to do something like this:
<input type="text" value={ value1 } >
<input if={ value1 != ''} type="text">
So, adding to DOM the second input when the first input has any value different than empty. I know 2-way data binding is not supported by Riot.js
I have tried to do the following:
<input ref="first" type="text" >
<input if={ this.refs.first.value != '' } type="text">
But it does not work.
You are correct, Riot does not do 2-way data binding for reasons I'll leave to the reader to research. It's fascinating stuff, but in my opinion, most web development can be made drastically simpler by following a few simple patterns. Riot is great for this reason. Simply put, the tag is just markup with event listeners that can update the tag.
<my-tag>
<input name='username' type='text' onKeyup={ checkVal } value={ opts.val }>
<input if={ usernameEntered } name='password' type='password'>
<script>
this.checkVal = (event) => {
this.usernameEntered = event.target.value !== ''
// this.update() is implicitly called in event listeners
}
</script>
</my-tag>
In your case (I don't know your exact use case), you may want to populate the first input element with a value passed into the tag (opts.val). Then we can assign some variable (usernameEntered) in an event listener (checkVal) and update the tag.
See Riot JS Guide for more detailed examples

getElementsByTagName of all siblings

UPDATE:
Let me rephrase.
I have multiple divs that all contain, among other things, an img element with the class="yes". But they're not all the same siblings.
Two examples:
<div id="div1" onclick="function(this)">
<img src="image1" />
<div>
<img src="image2" class="yes" />
</div>
</div>
<div id="div2" onclick="function(this)">
<img src="image3" class="yes" />
</div>
Now I'm trying to formulate one function for both divs that would change the source of the image with class yes.
getElementsByTagName doesn't seem to do the trick, nor does getElementsbyClassName.
Any thoughts? Thanks again!
getElementsByTagname is the wrong function.
There is no easy way to do what you're trying to do, unless you resort to third party libraries such as jQuery.
With jquery, you use this code:
$('img.yes').each(function() {
console.log(this);
});
Here is a working example of what you're trying to do: http://jsfiddle.net/ZYBp6/
You can use jQuery like this:
function some_function(x)
{
var arr = $("#" + x.id + " .yes"); // Gets all children of the class "yes"
}
Or if you only want to get img elements, you can do this instead:
function some_function(x)
{
var arr = $("#" + x.id + "img.yes");
}
In both of these examples, arr would contain DOM elements, and not the kind of "element" produced by jQuery normally.
This seems to work:
function function(x) {
$(x).find('.yes').attr('src','differentimage.png');
}

Add more css classes in one function

I need to create a function with this:
onMouseDown to add that class,onChange that other class and onBlur last class.
With ".animate" is more wonderful, but is ok even without.
onMouseDown="this.className='styleDropDownClick';
onChange="this.className='styleDropDown'";
onBlur="this.className='styleDropDown';
If anyoane can help me , thank's.
Try the following functions:
function styleDropDownClick() {
var textForm = document.forms["textForm"];
textForm.fname.setAttribute("class", "styleDropDownClick");
}
function styleDropDown() {
var textForm = document.forms["textForm"];
textForm.fname.setAttribute("class", "styleDropDown");
}
This works with the following HTML:
<form id="textForm">
<input type="text" class="styleDropDown" name="fname"
onBlur="styleDropDown()" onChange="styleDropDown()" onMouseDown="styleDropDownClick()" value="test"/>
<input type="text" class="styleDropDown" name="fname2" value="test2"/>
</form>
Fixed! My problew was that the child of select is not expanding with auto width or a given width.
$("select").click(function () {
$(this).children().addClass("cooling");
});
here is an example, it works only for IE
http://jsfiddle.net/DCjYA/132/