How do I make a Dropdown menu in AntD not display the three little dots next to it? - antd

If you look at the screenshot below, you can see what is being rendered:
rendering of antd dropdown with three dots
Code:
<Column title="Category" render={(text, record) => (
<Dropdown placement="bottomLeft"
overlay={
<Menu>
{productCategories.map(category => (
<Menu.Item key={category.id}>
<a href="#" onClick={(event) => {event.preventDefault(); }}>
{category.name}
</a>
</Menu.Item>
))}
</Menu>
}
>
<Dropdown.Button>
Category // eventually this will be the selected category name
</Dropdown.Button>
</Dropdown>
)} />
There are two problems I'm experiencing:
The three dots are appearing... I don't know why
Whenever I hover my mouse over the three dots, an error occurs: React.Children.only expected to receive a single React element child. and the page just goes blank.
Helpful answers appreciated.

The first error occurs because you are using Dropdown.Button instead of Button inside Dropdown.
The second error occurs because overlay props must be passed to Dropdown.Button
To fix both errors you need to replace Dropdown.Button with Button
<Column title="Category" render={(text, record) => (
<Dropdown placement="bottomLeft"
overlay={
<Menu>
{productCategories.map(category => (
<Menu.Item key={category.id}>
<a href="#" onClick={(event) => {event.preventDefault(); }}>
{category.name}
</a>
</Menu.Item>
))}
</Menu>
}
>
<Button>
Category // eventually this will be the selected category name
</Button>
</Dropdown>
)} />

Related

Capybara cannot select checkbox

I feel like I have tried everything, but I cannot select a checkbox in my application.
I have two checkboxes that look like this. One with 'cheese' and one with 'pickles'. they're auto generated with Rails form_with's = form.check_box
<input name="foods[]" type="hidden" value="0" autocomplete="off">
<input class="foodCheckbox" type="checkbox" value="cheese" name="food[]" id="food_cheese">
<a target="_blank" href="MyString">cheese</a>
Now to my testing. I have tried the following:
1.
check('food_cheese')
check('#food_cheese')
find("food_cheese").click
find("#food_cheese").click
find("food_cheese", visible: false).click
find("#food_cheese", visible: false).click
find(:css, "#food_cheese").set(true)
find(:css, "#food_cheese", visible: false).execute_script('this.checked = true')
The page finds the checkboxes. I cannot click the label because it is a link. When I do save_and_open nothing is selected. How do I select a checkbox?
You can use
find("#food_cheese").execute_script("this.click()")
or
page.execute_script("document.querySelector('#food_cheese').click()")

Using react-hook-form, how to programmatically modify values of inputs , depending on a selection?

Sounds simple, but I couldn't find a hello-world example of this, despite the richness of the doc. The closest I could find was in https://react-hook-form.com/advanced-usage, in the Working with virtualized lists section, but that relies on another module react-window, which introduces further complexity.
I want to allow the admin user to create-update-delete a list of products, with various properties.
My current code in JSX looks like this, I'd like to take advantage of error handling etc from react-hook-form:
<ol >
{products.map((row, index) => (
<li
className={index === selectedProductIndex ? "selected" : ""}
key={index}
id={index} onClick={handleSelectProduct}>
{row.name}
</li>
))}
</ol>
<form onSubmit={handleSaveProduct}>
<p>Product name: </p>
<input name="productName" type="text" value={selectedProductName}
onChange={handleEdit_name} />
(... more properties to edit here)
</form>
The handlers save the values of selectedProductName, selectedProductIndex, etc in useState, in a database via axios, etc.
I'm handling the values of each field individually in the useState, which I'm aware is laborious and heavy-handed.
Well the answer was quite simple, although it took me a while to figure it out.
In most of the examples, the onChange or onClick handlers don't use the event object, but nothing prevents you from adding it in. Then there's the setValue function to set the other control's value. Here's the code of a hello-world example. It offers one dropdown and one input field, the input field updates to match the selected value of the dropdown.
import React from "react";
import {useForm} from "react-hook-form";
function Test() {
const {register, handleSubmit, errors, setValue} = useForm();
const mySubmit = data => {
console.log(data);
}
return (
<div>
<form onSubmit={handleSubmit(mySubmit)} className="reacthookform">
<select name="dropdown" ref={register}
onChange={(ev) => setValue("productName", ev.target.value)}>
{["AAA", "BBB", "CCC"].map(value => (
<option key={value} value={value}>
{value}
</option>
))}
</select>
<input name="productName" defaultValue="AAA" ref={register({required: true})} className="big"/>
{errors.productName && <p className="errorMessage">This field is required</p>}
<input type="submit" value="Save product"/>
</form>
</div>
);
}
export default Test;

How do I use multiple submit buttons with react-final-form?

I want to build a form using react-final-form that has multiple submit buttons, where each submit button sets a different value in the form. Essentially, I want to create a form that looks something like this in rendered HTML:
<form>
Are you over 18 years old?
<button type="submit">Yes</button>
<button type="submit">No</button>
</form>
However, I can't figure out how to make react-final-form treat these different submit buttons as setting values in the form. I tried combining component state, <input type="hidden">, and onClick handlers, like this:
class FormWithMultipleSubmits extends React.Component {
state = {
value: undefined
};
setValue = value => this.setState({ value: value });
render() {
return (
<Form>
Are you over 18 years old?
<Field
name="adult"
component="input"
type="hidden"
value={this.state.value}
/>
<button type="submit" onClick={() => this.setValue(true)}>
Yes
</button>
<button type="submit" onClick={() => this.setValue(false)}>
No
</button>
</Form>
);
}
}
However, that doesn't seem to work -- probably because the value property on the <Field> component is only used for checkboxes and radio buttons.
Can someone give me a nudge in the right direction, for how to solve this properly?
Here's a Sandbox that shows how.

Select a button having multiple classes in capybara

I want to select button inside the first div
Following is the code using
<div id="1">
<button class="button btcls bns" data-dismiss="modal">create</button>
</div>
I used following method to select that button'
xpath('//btcls').click
But no one is working
within("#1") do
click_button("create")
end

jQuery UI Dialog Buttons Not Responding to click_button or selenium.click in Selenium/Webrat

Has anyone been able to get the jQuery UI Dialog buttons to respond to click_button or selenium.click? I can't seem to be able to get this to work.
Basically, I'm trying to test a form in a jQuery UI Dialog in a Rails app using Cucumber/Webrat/Selenium.
I have a page with many table rows, and each row on click fires off a dialog box with a form. Each form element has a unique id so the markup is valid.
Since the buttons can be created dynamically by the Dialog plugin, I initialize the dialog to add a 'Save' and 'Cancel' button. Interestingly, the plugin inserts a button tag, not an input tag. I also add ids on open as shown below, so the buttons can be targeted by the testing framework.
$('.inventory_dialog').dialog({
autoOpen: false,
modal: true,
buttons: {
'Save': function() {
// ajax submit stuff
},
Cancel: function() {
// cancel stuff
}
},
open: function() {
// add ids to buttons for selenium
var inventory_id = $(this).attr('id').split('_').pop();
$('.ui-dialog-buttonpane')
.find('button:contains("Save")').attr('id', 'inventory_'+inventory_id+'_save_button')
.end()
.find('button:contains("Cancel")').attr('id', 'inventory_'+inventory_id+'_cancel_button');
}
});
The markup looks like:
<div id="inventory_dialog_392827" class="inventory_dialog">
<form action="/suppliers/22/listings/27738/inventory/392827" class="edit_inventory" id="edit_inventory_392827" method="post"><div style="margin:0;padding:0"><input name="_method" type="hidden" value="put" /></div>
<div class="input_block">
<label for="inventory_392827_new_quantity">Quantity</label>
<input id="inventory_392827_new_quantity" name="inventory[new_quantity]" type="text" value="10" />
</div>
<div class="input_block">
<label for="inventory_392827_claim_quantities">Groups of</label>
<input id="inventory_392827_claim_quantities" name="inventory[claim_quantities]" type="text" value="6-8" />
</div>
</form>
</div>
My Cucumber step (presently) looks like:
When /^I click the "(.+)" button in the inventory dialog$/ do |button_name|
debugger
selenium.click "//button[#id='inventory_#{#current_offer.id}_#{button_name.downcase}_button']"
selenium_wait
end
When I run Cucumber and it hits 'debugger', I am able to manually 'selenium.click' in the input fields.
selenium.click "//input[#id='inventory_392827_new_quantity']"
This successfully puts a cursor in that field. However, clicking the button does not work:
selenium.click "//button[#id='inventory_392827_save_button']"
When I type that in the command line debugger, it returns nil (which I believe is success, since there is no exception), but Firefox doesn't do anything. The dialog box stays open in the browser. When I output response.body, that button is present.
I also tried
click_button "inventory_392827_save_button"
but the 'selenium_wait' command times out which means it doesn't see that element.
I'm stuck...
Does the problem go away if you change it to "fireEvent ... click" or to clickAt?
It might be better to locate your button by another location strategy such as XPath or CSS. If you add the HTML of the button(s) then I'll try to give some suggestions.
If your target button has a class of 'submit' for example you could use:
css=input.submit
If the target button has a value of 'Click Me' you could use:
//input[#value='Click Me']
Another suggestion would be to use the id attribute without the unique number, so the following may work for you:
//input[substring(#id, string-length(#id) -11, 12) = '_save_button']
I had a similar problem, and here's how i got it done (using Capybara/Selenium/Factory_Girl).
The jQuery UI Dialog buttons generates this HTML, in my case with two buttons Add and Cancel:
<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
<button type="button" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" role="button" aria-disabled="false">
<span class="ui-button-text">Add</span>
</button>
<button type="button" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" role="button" aria-disabled="false">
<span class="ui-button-text">Cancel</span>
</button>
</div>
But the click_button method doesn't work because the actual button name is a span
nested inside the button tag, as you can see above.
So i wrote in the .feature step:
When I press the jquery dialog "Add" button
And i added this to my 'base.rb':
# jQuery Dialog buttons
When /^I press the jquery dialog "([^\"]*)" button$/ do |button_text|
page.find("div.ui-dialog-buttonpane").find('span', :text => button_text).click
end

Resources