Change Formik to react-hook-form v7 - react-hook-form

I am refactoring a Formik form to react-hook-form v7. The Formik form has this structure:
<FormikProvider value={form}>
<Form>
<Field
component={FighterInput}
fighterAvailability={fighterAvailabilityStatus}
/>
<StandardButton
type="submit"
>
</StandardButton>
</Form>
</FormikProvider>
The FighterInput component is a component which has an input field and a function that renders a div based on fighter availability.
I need to get the typed in value character by character because a useEffect triggers other functions so I need to use react-hook-form watch or something else that let's me grab every character that is typed in to the {FighterInput} component, this is currently achieved with Formiks context values, but I need to do this in react-hook-form.
I've been able to get the value using watch with the following approach:
const fighter = watch('fighterInput');
<form>
<input {...register("fighterInput")} />
</form>
But this is not using the {FighterInput} component. The {FighterInput} component accepts props and returns an an input field. It also has some functions that renders a div based on conditionals set in the useEffect in the main component where I want to use react-hook-form and import {FighterInput}
How can I transform the Formik form with the above structure to achieve the same thing using react-hook-form v7 and render the {FighterInput} component while being able to grab every character on-the-fly as it is being typed into the input of {FighterInput} ?
<Controller
control={control}
name="test"
render={({
field: { onChange, onBlur, value, name, ref },
fieldState: { invalid, isTouched, isDirty, error },
formState,
}) => (
<FighterInput
onChange={onChange} // send value to hook form
checked={value}
inputRef={ref}
{...register("fighterInput")} // not working
/>
)}
/>
In addition to being able to watch the input, I need to be able to access form values in my FighterInput component as well and wondering how I can do that, am I supposed to use react-hook-forms useFormContext or FormProvider?

Related

Using Text Mask component with Ant design Input

I have been testing 'react-text-mask' library and I want to use this component together with ant design Input component using its render attribute. However, it doesn't show formatted text.
<TextMask
mask={[/[12]/, /\d/, /\d/, /\d/, "-", /[01]/, /\d/, "-", /[0-3]/, /\d/]}
placeholderChar="_"
showMask
render={(ref, props) => (
<Input
name="phone"
className="form-control"
placeholder="Hey I am Ant design Input"
required
ref={ref}
{...props}
/>
)}
/>
If I change the tag with It shows formatted text like we expect.
My main intention to show every input component should be displayed like an ant design component.
demo
You can make it using react-input-mask library.

Is there a way to update textarea 2 simultaneously while typing text in text area 1 using JSF ajax features? [duplicate]

I am trying to implement jQuery with PrimeFaces and JSF components, but it's not working properly. When I tried to do the same with HTML tags it;s working properly.
Here is the code with HTML tags which works properly with jQuery:
<input type="checkbox" id="check2"></input>
<h:outputText value="Check the box, if your permanent address is as same as current address."></h:outputText>
<h:message for="checkbox" style="color:red" />
with
$("#check2").change(function() {
if ($("#check2").is(":checked")) {
$("#p2").hide();
} else {
$("#p2").show();
}
});
Here is the code with PrimeFaces/JSF which doesn't work properly with jQuery:
<p:selectManyCheckbox >
<f:selectItem itemLabel="1" value="one" id="rad" ></f:selectItem>
</p:selectManyCheckbox>
with
$("#rad").change(function() {
if ($("#rad:checked").val() == "one") {
$("#p2").hide();
} else {
$("#p2").show();
}
});
You should realize that jQuery works with the HTML DOM tree in the client side. jQuery doesn't work directly on JSF components as you've written in the JSF source code, but jQuery works directly with the HTML DOM tree which is generated by those JSF components. You need to open the page in webbrowser and rightclick and then View Source. You'll see that JSF prepends the ID of the generated HTML input elements with the IDs of all parent NamingContainer components (such as <h:form>, <h:dataTable>, etc) with : as default separator character. So for example
<h:form id="foo">
<p:selectManyCheckbox id="bar" />
...
will end up in generated HTML as
<form id="foo" name="foo">
<input type="checkbox" id="foo:bar" name="foo:bar" />
...
You need to select elements by exactly that ID instead. The : is however a special character in CSS identifiers representing a pseudo selector. To select an element with a : in the ID using CSS selectors in jQuery, you need to either escape it by backslash or to use the [id=...] attribute selector or just use the old getElementById():
var $element1 = $("#foo\\:bar");
// or
var $element2 = $("[id='foo:bar']");
// or
var $element3 = $(document.getElementById("foo:bar"));
If you see an autogenerated j_idXXX part in the ID where XXX represents an incremental number, then you must give the particular component a fixed ID, because the incremental number is dynamic and is subject to changes depending on component's physical position in the tree.
As an alternative, you can also just use a class name:
<x:someInputComponent styleClass="someClassName" />
which ends up in HTML as
<input type="..." class="someClassName" />
so that you can get it as
var $elements = $(".someClassName");
This allows for better abstraction and reusability. Surely those kind of elements are not unique. Only the main layout elements like header, menu, content and footer are really unique, but they are in turn usually not in a NamingContainer already.
As again another alternative, you could just pass the HTML DOM element itself into the function:
<x:someComponent onclick="someFunction(this)" />
function someFunction(element) {
var $element = $(element);
// ...
}
See also:
How can I know the id of a JSF component so I can use in Javascript
How to use JSF generated HTML element ID with colon ":" in CSS selectors?
By default, JSF generates unusable IDs, which are incompatible with the CSS part of web standards
Integrate JavaScript in JSF composite component, the clean way
You also can use the jQuery "Attribute Contains Selector" (here is the url http://api.jquery.com/attribute-contains-selector/)
For example If you have a
<p:spinner id="quantity" value="#{toBuyBean.quantityToAdd}" min="0"/>
and you want to do something on its object you can select it with
jQuery('input[id*="quantity"]')
and if you want to print its value you can do this
alert(jQuery('input[id*="quantity"]').val());
In order to know the real html tag of the element you can always look at the real html element (in this case spinner was translated into input) using firebug or ie developer tools or view source...
Daniel.
If you're using RichFaces you can check rich:jQuery comonent. It allows you to specify server side id for jQuery component. For example, you have component with specified server id, then you can apply any jQuery related stuff to in next way:
<rich:jQuery selector="#<server-side-component-id>" query="find('.some-child').removeProp('style')"/>
For more info, please check doumentation.
Hope it helps.
look this will help you when i select experience=Yes my dialoguebox which id is dlg3 is popup.and if value is No it will not open

AngularDart component not working with ng-repeat but other tags do

I can do a ng-repeat with a input tag as follows.
<input ng-repeat="r in cmp.rooms track by $index" type="text" value="{{r.name}}" />
I made a AngularDart component called <radio_component>, so side by side.
<input ng-repeat="r in cmp.rooms track by $index" type="text" value="{{r.name}}" />
<radio_component ng-repeat="r in cmp.rooms track by $index"
textLabel="{{r.name}}"></radio_component>
The textLabel is defined in my component as
#NgAttr('textLabel')
String textLabel;
Now it works with text if I set textLabel="HELLO", but it does not work with textLabel="{{r.name}}". I don't understand why? If I include textLabel="{{r.name}}" it doesn't work. Any clues?
To clarify the question and hopefully make it reproducible, here are some test files. The two files are test_component.dart and test_component.html
library minutesheet_component_radiobox;
import 'package:angular/angular.dart';
import 'dart:html';
#Component(
cssUrl: 'http://localhost:8888/assets/css/admin/module.admin.stylesheet-complete.sidebar_type.no-sidebar.min.css',
publishAs: 'test_component',
selector: 'test_component',
templateUrl: 'packages/minutesheet/component/test_component.html')
class TestComponent extends AttachAware with ShadowRootAware {
// Chose either NgAttr or NgOneWay
//#NgAttr("textLabel")
//String textLabel;
String _textLabel;
#NgOneWay('textLabel')
String get textLabel => _textLabel;
set textLabel(String val) {
print(val); _textLabel = val;
}
void attach() {
}
void onShadowRoot(ShadowRoot shadowRoot) {
}
}
The html file for this component.
<div class="radio radioCheckbox">
<label class="radio-custom">
<i class="fa fa-circle-o" style="padding-top:1px"></i>
{{test_component.textLabel}}
</label>
</div>
Using these two files I have found that when I use the component the following is true.
If using #NgOneWay then null is passed into the set textLabel if I am using ng-repeat as follows:
<test_component ng-repeat="r in cmp.rooms track by $index" textLabel="{{r.name}}" />
If using #NgOneWay passing a string then null is also passed into the set textLabel:
<test_component ng-repeat="r in cmp.rooms track by $index" textLabel="HELLO" />
If using #NgAttr and passing the variable {{r.name}} then no value is shown on the HTML page.
If using #NgAttr and passing a "HELLO" then the word HELLO is shown on the HTML page.
If using #NgOneWay and using r.name in textLabel actually passes in the value to set textLabel on the component, however I do not see the value in the output HTML.
<test_component ng-repeat="r in cmp.rooms track by $index" textLabel="r.name" />
If using #NgTwoWay and using r.name in textLabel actually passes in the value to set textLabel on the component AND I do see the value in the HTML output.
<test_component ng-repeat="r in cmp.rooms track by $index" textLabel="r.name" />
Ok so #NgTwoWay works BUT now I cannot pass a normal string into the test component if I do it this way. If I then have.
<test_component textLabel="Hello there" />
Then I get this error.
Parser Error: 'there' is an unexpected token at column 7 in [Hello there]
Perhaps this is solved now, I am not sure if this is how it is supposed to work or if its working this way within my application due to some other code making it work strangely. Regardless, for me, it is at a point where I can get my application working, so I am happy enough for the time being.
Finally thanks to Gunter, it appears if the attribute of the component is named text-label and NOT textLabel AND #NgTwoWay is used, it works as expected in the first case. So its solved.
The moral of the story is, do not make component attributes with any upper case characters. (?)
#NgAttr doesn't work with camel case attribute names. See discussion below.

How can I tweak Knockout's writeable computed observeables to work with MVC model binding?

I have a value for user display and a similar value for storage. How can I modify what I have so that I save the correct data to the model?
Fiddle
HTML
<div>formatted value for user display</div>
<input type="text" data-bind="value: formattedUnitOfCost" id="Model_Bound_ID" />
<div>unformatted value (the one I'd like to save)...this is not model bound</div>
<input type="text" data-bind="value: unitOfCost" />
JavaScript/Knockout
function AppViewModel() {
var self = this;
self.unitOfCost = ko.observable(1.01).extend({
isServerSet: false
});
self.formattedUnitOfCost = ko.computed({
read: function () {
return '$' + self.unitOfCost().toFixed(2);
},
write: function (value) {
// Strip out unwanted characters, parse as float, then write the raw data back to the underlying "price" observable
value = parseFloat(value.replace(/[^\.\d]/g, ""));
self.unitOfCost(isNaN(value) ? 0 : value); // Write to underlying storage
},
owner: self
});
}
ko.applyBindings(new AppViewModel());
The unformatted value is not displayed to the user. Model_Bound_ID is user editable.
You're doing it the wrong way.
Your model bound control (I mean the control that will be posted to your controller, and has the unformatted value) should be created like any other control, for example using Html.HiddenFor or whatever you want in your (Razor?) template. And you must add the data-bind attribute in the template. Remember that low-dash will be converted in medium-dash, so you can add it in the attributes parameter of the Html Helper like this: { data_bind = "value: unitOfcost" }.
Obviously this hidden field will be sent to the controller when posted (direct post, ajax, or whatever).
Now you need to add the visible control, and bind it to another observable. This observable will be a computed observable, which will do this:
on read, it will take the value from unitOfWork, and return it formatted
on write, it will parse the value to convert it to number, and update the unitOfWork observable with the parsed value
In fact you've got nearly all the code, but were implementing it all the way back.
Another way of looking at this answer is to change the html from this:
<input type="text" data-bind="value: formattedUnitOfCost" id="Model_Bound_ID" />
<input type="text" data-bind="value: unitOfCost" />
to this
<input type="text" data-bind="value: formattedUnitOfCost"/>
<input type="text" data-bind="value: unitOfCost" id="Model_Bound_ID" />
And KO does the rest by the power of the observables. Gosh I love KO

Display label before input using formRow view helper in Zf2

In Zend Framework 2.1.4 I am using the standard form view helpers to render out my form elements.
When I try:
<?php echo $this->formRow($form->get('Title'));?>
The label text and input element are placed within the label:
<label>
<span>Title</span><input type="text" name="Title" placeholder="Inserisci titolo"
required="required" value="">
</label>
The same with:
<?php echo $this->formCollection($form, TRUE);
However, if I render out the label and input individually:
echo $this->formLabel($form->get('Title'));
echo $this->formInput($form->get('Title'));
It generates the html I want:
<label for="Title">Title</label>
<input type="text" name="Title" placeholder="Insert Title" required="required" value="">
How can I achieve the same with the formRow view helper?
If a form element does not have an "id" attribute, the label will wrap the input:
<label>Label<input /></label>
Otherwise:
<label for="test">Label</label><input id="test" />
Looking at (zf2 version 2.25 dev):
\Zend\Form\View\Helper\FormRow
It appears that if you don't provide an id for your form elements, the default general behaviour is to place the input element inside their corresponding label element.
The second argument for the formRow view helper, will place the label text before (prepend) or after (append) the input element in the document flow. (The default is to place it before.)
Check the render method for more details.
In first you must look source code to understand how formRow works : https://github.com/zendframework/zf2/blob/master/library/Zend/Form/View/Helper/FormRow.php
After you'll see in this code that __invoke has $labelPosition parameter that you can prepend or append with const LABEL_APPEND and LABEL_PREPEND.
In short, try to do something like this :
$this->formRorw($form->get('element'), 'prepend'); // Or append as you want

Resources