Angular 2 - Using pipe in (click) event - events

My question is probably simple but just can't find the way to use pipe within an event like (click) for example. Something like this:
<button (click)="quizAnswers(answer?.texte | translate | async)"></button>
I always get an error. I tried to wrap it with () or {} or []...
There are some workaround like putting the content in an attribute and then get it on the event with this.attribute but I'm sure there is a proper way !
Thanks in advance for your help

A workaround would be to call your pipes in the click handler function instead:
function quizAnswers(answer)
{
let translatePipe= new TranslatePipe();
...
return translatePipe.transform(answer?.texte);
}

I just got through this same issue. Action expressions can't contain the async pipe. However, you can use a hidden <input> element to hold the latest value of the promise/observable stream, and then access that value anywhere.
<input #dummy style="{display: none}" type="text" value="{{ myAsyncSource | async }}">
<a (click)="myFunction(dummy.value)">{{ dummy.value }}</a>
For your case of <button> there's actually a one-line solution that eliminates the need for the dummy <input>, posted in this solution:
<button type="button" #item value="{{i$ | async}}" (click)="buttonClicked(item.value)">BUTTON</button>

Related

Laravel 9 - Submitting a form to a route leads to /null and doesn't do anything

I'm using soft deletes and trying to make a function to restore the deleted row. Really everything to do with submitting the form doesn't work, even deleting...
My tags are within a forelse loop, maybe that's the cause??
Route is (this is above my resource route):
Route::post('/post/restore/{id}', [PostController::class, 'restore'])
->name('post.restore');
Controller is:
public function restore($id)
{
dd($id);
}
Form/view is:
<form action="{{route('post.restore', $post->id)}}" method="POST">
#csrf
<button type="submit" class="dropdown-item popup" data-confirm="Would you like to restore?">Restore</button>
</form>
After submitting, it just takes me to:
domainURL/post/null
and gives a 404 error
Any advice?? I also tried it without the {id} at the end of the route, same results
I think you are using the wrong syntax for route function, instead of this:
route('post.restore', $post->id)
you should use it like this:
route('post.restore', ['id' => $post->id])
you can read more here as well.
I figured it out... my "would you like to restore?" javascript function was breaking the form. I was using javascript to popup a confirmation message before submitting and during that process it lost the ID
I got rid of that and it works fine
Thank you!

Cypress picks up the wrong element?

I am trying to find and click this element using Cypress:
<input class="form-control btn btn-primary" type="button" value="Log out">
I have tried several variations, but the closest is this:
cy.get("input[type='button']").filter('.btn-primary').should('have.value','Log out').click()
So when I run this, I get the following response:
expected [ <input.form-control.btn.btn-primary>, 1 more... ] to have value Log out, but the value was Edit.
Sure, there is a button there called Edit, but it is not the one I want. I have specified what I want with the should('have.value','Log out') clause.
So - why does it insist on trying to use the wrong element & failing?
Update: I finally got this working.
This is the solution I went with in the end:
cy.get("input[type='button']").filter('.btn-primary').eq(1)
.should('have.value','Log out').then(($btn) => {
$btn.click()
})
can you try
cy.get('input').find("[value='Log out']").click()
or
cy.get("[value='Log out']").click()
Obviously you need your developers to add ids, but I know your situation.
You could also try if there is only one btn-primary
cy.get('.btn-primary').click()
This was the solution that worked for me:
cy.get("input[type='button']").filter('.btn-primary').eq(1)
.should('have.value','Log out').then(($btn) => {
$btn.click()
})
How about to set an unique testID for that button and get it as simple as it can be.
Something like:
data-test-id= "log-out-button" //put that in your button code
and then in Cypress:
cy.get('[data-test-id="log-out-button"]')
.click()
even though you can set a function to get those testID's more effectively:
Command.Cypress.add('getTestID', (testID) => {
cy.get(`[data-test-id="${testId}"]`)
})
and now everything you do for getting that button (or every element with testID is: cy.getTestID('log-out-button')

prototype : onclick remove previous element

i have html as below in which onclick of <a> i want to remove the text box above it.
<input class="sku-box" class="input-text validate-number" type="text" title="file-number" name="sku[]">
<a value="remove" onclick="remove()" href="javascript:void(0);">remove</a>
<input class="sku-box" class="input-text validate-number" type="text" title="file-number" name="sku[]">
<a value="remove" onclick="remove()" href="javascript:void(0);">remove</a>
my solution to this, i changed the <a> tag to this.
remove
and my prototype function look like this
function removefield(ele)
{
$(ele).previous().remove();
ele.remove();
}
You have several options for observing click events, and usually I wire up click events after the dom is loaded using something like:
document.on('click', 'a', myFunction.BindAsEventListener())
The above statement sets you up for observing all click events occurring for the a element firing up the function myFunction. Once you have this established you can then either trap the event or simply allow it to bubble up or do both, trap and bubble up the event.
However, with the direction you are going there you would be better off to pass the identity of your a tag to the remove function, then it is easy to remove the previous element. So you would have:
<a id="a_tag1" value="remove" onclick="remove('a_tag1')" href="javascript:void(0);">remove</a>
Then your function remove might look something like this:
function remove(a) {
// prev element
var elm = $(a).previous('input');
// remove it
if(elm)
elm.remove();
}
This is very basic and in reality you would need to do things to guarantee that the previous input element you are grabbing is associated with the a element you clicked. You could do this by agreeing on a new data-xxxx element tag or an arbitrary class name you can use to compare the elements. For example, your a tag might look like:
<a data-group='monkeys'>...</a>
And the cooresponding input tag might look like:
<input data-group='monkeys'>...</input>
Then, in the above code where you call previous on the a tag, you would construct your select to include a test on the data-group value that matches the current a tag.
Karl..

How to send list value in Ruby Sinatra?

I have a simple form where there is a list:
<form method ="post" action ="">
<select>Select subject
<option value="1">Maths</option>
<option value="2">Science</option>
</select>
<input type="submit" name="Submit" />
My question is, if I select the option Maths, I would like the value to be sent eg /1.
What should be written in action? How should the route be written ?
get '' do
end
Your route could look something like this:
post '/subject' do
#subject = params[:subject]
# do whatever you want now
end
But you would need to give your select tag a name and your form an action:
<form method="post" action="/subject">
<select name="subject">
<!-- etc etc -->
Also have a look at related questions.
we tend to look at queries as GETs (makes sense, it is after all retrieving information)
rather than a POST which (doesn't actually change data) yet responds with a result page
a common (gnarly) pattern we often see is to rewrite (in js or redirect)
to the form
GET '/search/:q1/and/:q2' do
// result of search filtered by q1 and q2
end
which is also quite neat

How to serialize a form with dynamically added inputs using jQuery?

I've read through a lot of questions addressing similar question but I can't get a grip on it, yet.
I have a simple HTML form just like
<form id="edit-items" name="edit-items" onsubmit="saveItems();">
<input type="submit" value="Save">
<input class="item" id="ei81" type="hidden" name="i[81]" value="1">
<input class="item" id="ei124" type="hidden" name="i[124]" value="1">
</form>
The two existing hidden inputs could be set upon document loading due to a prior save.
Now I have images (kind of a menu). If they are clicked a corresponding hidden input is appended to the form:
<img id="i37" class="clickable-item" src="items/i37.gif" title="item name" onclick="addItem(37,1)" />
The addItem function:
function addItem(id,n) {
var zitem = $("#e"+id);
if ( 0 in zitem ) {
if ( zitem.val() > 0 ) {
var newcnt = parseInt(zitem.val()) + n;
if ( newcnt <= 0 ) {
zitem.remove();
}
else {
zitem.val(newcnt);
}
}
}
else if(n == 1) {
var iform = $("#edit-items");
iform.append("<input class=\"item\" id=\"e"+id+"\" type=\"hidden\" name=\"i["+id+"]\" value=\"1\">");
}
}
This part all works correct, after clicking the image, my form looks like
<form id="edit-items" name="edit-items" onsubmit="saveItems();">
<input type="submit" value="Save">
<input class="item" id="ei81" type="hidden" name="i[81]" value="1">
<input class="item" id="ei124" type="hidden" name="i[124]" value="1">
<input class="item" id="ei37" type="hidden" name="i[37]" value="1">
</form>
which is exactly what I want. But then when hitting the submit button only the first two elements are submitted (the ones which have not been added dynamically).
Now, I read a lot about .bind and .live handlers but I am missing some point obviously. I tried to delete the onclick attribute on the images and to bind the .live to them since they are causing the new inputs:
$(".clickable-item").live("click", function() {
addItem($(this).attr("id"),1);
});
However, the ID is not transferred which is needed, though (hence no correct input is added). I learned that .live doesn't bind the handler to any elements but to the event.
Is it even possible to pass the element which has been clicked to the live handler?
Should the images even be watched by .live or should it be bound to something else?
The last thing I learned form another question here is that the inputs should be watched by .live, since they are dynamically added. But what kind of event I would attach? The inputs themselves are not clicked.
I would really appreciate any help as I am cracking my head and starting to get lost on that one.
Thanks in advance,
Paul
Regarding live() [docs]: this refers to the clicked element, so you can pass it to addItem with addItem(this, 1). This part of your code should work.
If you don't add or remove images dynamically then there is no reason to use live. You can just use click() [docs] (and yes, don't use onclick in the HTML).
But I see another problem:
The image id is i37. $(this).attr("id") will return this value.
In your addItem function you then take this value and perform string concatenation. The result will be $("#ii37") (note the two is).
The input element you create will have the id ii37 and not i37.
If you correct this to match it with the other elements like in your example (i.e. i37) , you will have problems because you have several elements with the same id (the input element and the image). If the image comes before the input field in the hierarchy, then $("#i37") will always select the image and you cannot call .val() on an image.
As I don't know what is the overall purpose of the code and what you want to do, I cannot give any suggestion how to improve this. Maybe it is enough to just change the prefix of the image and input field ids.
I learned that .live doesn't bind the handler to any elements but to the event.
That is not correct. .live() binds the event handler to the document root. Events, if not cancelled, bubble up the DOM tree, so they reach the root eventually. There, the event.target [docs] property is examined to determine the element that was clicked.

Resources