How to dynamic change the component type in FieldArray - redux-form

I have a FieldArray, and I want to change one of the Field's component type when adding a new line of Fields for it ( this.props.array.push("xxx", { obj })).
For example, I have a value named summaryNo.
When summaryNo === 0, I want the Field became a Picker. Else, as a simeple input Field.
Is that possible? I gave a try like the below codes:
export const renderInputOrPicker = ({ input, label, children, ...custom) => {
if (input.value instanceof Array && input.value[0] === "toBeAPicker") {
return (
<Picker mode="dropdown" {...input}
selectedValue={input.value[1]}
onValueChange={(value) => {
setTimeout(() => {
input.onChange(value);
}, 10);
}} children={children} {...custom} />
);
} else {
return (
<Item regular>
<Input {...input} />
</Item>
);
}
};
Any suggestion?
Thanks.

I thought I have figured a way out. I just don't need the input Field. What I want to do is to have a Field that can display "true" or "false" and can be controlled by the disable status.
The Picker Field can do that already. Which means I can let it read-only or editable and showing the current value.
All in all, I am still looking for the answer, a better solution for this redux form scenario!
Thanks.

Related

#fluentui/react DetailsList with the Column headers always Showing

Any way I can make the Column headers of my #fluentui/react "DetailsList" always show at the top when scrolling down?
Is there another #fluentui/react that does it?
Thank you
This is now possible with a Sticky control, and a ScrollablePane.
Information from here:
https://developer.microsoft.com/en-us/fluentui#/controls/web/scrollablepane
First, you'll need to define a ScrollablePane around your list, and provide a custom header renderer.
<ScrollablePane scrollbarVisibility={ScrollbarVisibility.auto}>
<MarqueeSelection selection={this._selection}
isDraggingConstrainedToRoot={true} >
<DetailsList compact={true} items={items} columns={this._columns}
selectionMode={SelectionMode.multiple}
selection={this._selection}
selectionPreservedOnEmptyClick={true}
onRenderDetailsHeader={this.renderFixedDetailsHeader} />
</MarqueeSelection>
</SrollablePane>
Then you'll need to provide a header renderer (onRenderDetailsHeader), like this for example
private renderFixedDetailsHeader: IRenderFunction<IDetailsHeaderProps> = (props, defaultRender) => {
if (!props) {
return null;
}
const onRenderColumnHeaderTooltip: IRenderFunction<IDetailsColumnRenderTooltipProps> =
tooltipHostProps => (
<TooltipHost {...tooltipHostProps} />
);
return (
<Sticky stickyPosition={StickyPositionType.Header} isScrollSynced>
{defaultRender!({
...props,
onRenderColumnHeaderTooltip,
})}
</Sticky>
);
}
Hey Presto!

Force react-select to show all options using Elasticsearch

I'm trying to implement this with elasticsearch and it is working But how i can force this show results which can be different from the searched terms? For example i search ardino, The elasticsearch give me the word arduino but then react-select does not show that result because ardino does not contain arduino. I know the idea of this library is exactly that and it is working ok, but i have most of the things already implemented and it is only missing that part.
The handle is giving the right behavior and it is populating the options correctly.
Thank you
<Select
name= {this.state.selectedOption}
value={this.state.selectedOption}
isSearchable={true}
onChange = {(val) => {
this._handleSearch(val.value)
}}
onInputChange = {(val) => {
this._handleSearch(val)
}}
options={this.state.options}
/>
I would recommend using the Async component which can simplify your code. You will not need the onChange handler anymore.
isSearcheable is true by default, no need to specify.
In answer to your question: Make sure you are passing in label and value keys with each result option. If you want to customize any of the results, for example adding the search term in the results, you can manually manipulate the options array.
import React, {Component} from 'react';
import AsyncSelect from 'react-select/lib/Async';
class Search extends Component {
state = {inputValue: ""}
onInputChange = (inputValue) => {
this.setState({ inputValue });
};
getSearchResults = async (inputValue) => {
// elastic search results
let options = await fetch(`searchElastic/${inputValue}`);
// input value of drop-down
const inputValue = this.state.inputValue;
// manually add input field as an option in drop-down
if (inputValue.length > 0)
options.unshift({label: inputValue, value: inputValue})
// async handling of new props
return options.map(opt => {
return {label: opt.name, value: opt.value}
})
}
render() {
return <AsyncSelect
onInputChange={this.onInputChange}
loadOptions={this.getSearchResults}
/>
}
}
export default Search;

Input base on some value changed

function Form(props) {
var objBarCode;
if (props.record && props.record.type === "STOCK") {
objBarCode = < TextInput source="barcode" label="Bar Code" / >;
}
return (
< SimpleForm {...props} >
< TextInput source="item" label="item" validate={[required]} / >
< TextInput source="name" label="Name" validate={[required]} / >
< SelectInput
source="type"
label="Type"
validate={[required]}
choices={[
{ id: "STOCK", name: "Stock" },
{ id: "RMK", name: "Remark" },
{ id: "SVR", name: "Services" }
]}
/ >
{objBarCode}
< /SimpleForm >
);
}
How can I achieve something like this, where some inputs only appear by some conditions? The above code does not rerender when the condition value changes. The goal was to have the Textinput Bar Code only appear when type="STOCK"
This won't be easy. You'll have to implement a custom input which will get the current value for the condition from the redux form state and decide what to display accordingly.
I suggest you create it as a wrapper or HOC so that you can reuse it.
You'll also have to explore the Admin-on-rest source to find the form key in redux and redux-form documentation for how to get the value.
However as this is a very common scenario, I'll see what we can do to make it easier:
We just released aor-dependent-input ! Let us know if that works for you :)

Can I add conditions within Kendo().DropDownList() definition?

I have a kendo dropdownlist and want to add a property to it but only if some condition is met. It that possible and, if so, what is the syntax? Below is the concept that I have in mind.
#(Html.Kendo().DropDownList()
.Name("My Dropdown List")
.Value(Model.xxx)
If (some condition){
.Height(1000)
}
.DataTextField("MYDESCRIPTIEN")
.DataValueField("MYFIELD")
.HtmlAttributes(new { style = "width:300px" })
)
Update: With regard to the Height, I am afraid you are out of luck, as the Height() method expects a non-null integer value that will be always serialized to the client. The only option is to use two different widget declarations inside an external conditional statement.
===
Each fluent method expects a value of a certain type, or an expression that returns a value of this type. In addition, each configuration setting has a default value.
So you have a couple of options:
use a ternary operator that returns different values, depending on the condition. In one case it may return the property's default value
use an auxiliary variable, that is assigned the appropriate value in advance
Fluent methods that expect an action can be managed differently and you can use standard conditional statements, instead of ternaries.
Here is an example for all above scenarios:
#{
bool myCondition = false;
}
#(Html.Kendo().DropDownList()
.HtmlAttributes(myCondition ? new { style = "width: 100%" } : new object { /* empty object */ } )
.Events(e => {
if (myCondition)
{
// nothing here this time
}
else
{
e.DataBound("onDataBound");
}
})
)
<script>
function onDataBound(e) {
console.log("dataBound");
}
</script>
Hi there you should be able to add Events like so:
#(Html.Kendo().DropDownList()
.Name("My Dropdown List")
.Value(Model.xxx)
.DataTextField("MYDESCRIPTIEN")
.DataValueField("MYFIELD")
.HtmlAttributes(new { style = "width:300px" })
.Events(e => e.Change("OnDropDownChanged"));
)
JAVASCRIPT
function OnDropDownChanged(e)
{
//Do stuff to meet condition
}

Knockout checked binding issue

I'm having a problem with checkbox bindings not quite working with KnockoutJS 2.0. I have an array of objects. One of the properties of those objects is an array of different objects. In the child objects there are a few properties, one of which is a boolean. I build a list for each parent object and under each parent I show the children. For each list of children I have two views, a read only and an edit view. In the read only I have images that represent whether or not the item is checked based on the boolean property. This works and if I update the boolean value through the console, I'm seeing what I would expect--the image goes away or displays based on the value I assign. In the edit view, the images are replaced with a checkbox. I see the same behavior when I update the value through the console--it is checked when I expect it to be and not when I don't. The problem comes in when I check or uncheck the checkbox. Doing this doesn't change the underlying value the checkbox is bound to.
Here's the basic idea of my data.
[
{
"xxx": "yyy",
"xxx": "yyy",
...
"Displays": [
{
"xxx": "yyy",
...
"Excluded": false,
},
{
"xxx": "yyy",
...
"Excluded": true,
}
],
}
]
Here's the binding
<input type="checkbox" data-bind="checked: !Excluded()" />
the problem is that "checked" here is a bidirectional binding: the bound property needs to be read to generate the correct view, but needs also to be updated when you click on the checkbox. Contrast this to a binding like:
<span data-bind="text: 'your name is ' + name()"></span>
when the expression is only read, so you can use an expression (and you need to unwrap the observable).
So, you need to bind directly to the observable property, without "unwrapping" it adding '()', it will be done by knockout when needed, both for read and write:
<input type="checkbox" data-bind="checked: Excluded" />
See http://jsfiddle.net/saurus/usKwA/ for a simple example. Note how the checkbox labels are updated on change, showing that the model is updated and the rendering triggers correctly.
If you need to negate the value (so that the checkbox is checked when the value is false), you can add a writeable computed observable, as explained on http://knockoutjs.com/documentation/computedObservables.html section "Writeable computed observables", or you can negate the data in the viewmodel, doing it on the server just before sending the data, or on the client before populating the viewmodel.
hope this helps.
I know my answer is a bit late to the game here, but I had this problem today and this was the closest thread I could find related to the problem, and it doesn't seem to have an answer that solves it. So here's my solution.
Essentially, the issue is that knockout really wants your viewModel values to be a string, not a boolean, but this isn't always practical. So, I created a binding called "isChecked" which works strictly with booleans. Note: This will only work with observable properties.
ko.bindingHandlers.isChecked = {
getElementDeclaredValue: function (element) {
var declaredValue = element.getAttribute("value");
// If a value is provided, we presume it represents "true",
// unless its explicitly "false". If no value is provided, we
// presume that a checked state would equal "true".
return declaredValue && Boolean.isBool(declaredValue)
? Boolean.parse(declaredValue)
: true;
},
init: function (element, valueAccessor) {
var updateHandler = function () {
var declaredValue = ko.bindingHandlers.isChecked.getElementDeclaredValue(element);
var elementValue = element.checked ? declaredValue : !declaredValue;
var modelValue = valueAccessor();
var currentValue = ko.utils.unwrapObservable(modelValue);
if (elementValue === currentValue)
return;
if (ko.isObservable(modelValue)) {
modelValue(elementValue);
}
};
ko.utils.registerEventHandler(element, "click", updateHandler);
},
update: function (element, valueAccessor) {
var elementValue = ko.bindingHandlers.isChecked.getElementDeclaredValue(element);
element.checked = elementValue === ko.utils.unwrapObservable(valueAccessor());
}
};
The two Boolean methods ("parse" and "isBool") are defined as follows:
Boolean.isBool = function (value) {
return (/^(?:true|false)$/i).test(value);
};
Boolean.parse = function (value) {
return (/^true$/i).test(value);
};
I'll ignore any comments that say I shouldn't be modifying a built-in object prototype; I'll do as I damn well please ;-).
Usage is the same as the checked binding. The "value" attribute is optional, unless you want the checked state to represent false:
<input type="radio" id="rbNewClaim" name="ClaimType" value="false" data-bind="checked: isExistingClaim" />
Hope this helps someone.
I gave up trying to get this to work with the bool values and created an array of selected objects and handled it that way. It isn't the optimal solution, but I was tired of fighting this.

Resources