I'm using Laravel Nova, and I want to make "Save" button(on the Update view) unavailable while all required fields are empty.
Here's the part of the code of the "Update.vue" file that creates my form fields:
<div v-for="field in fields">
<component
#file-deleted="updateLastRetrievedAtTimestamp"
:is="'form-' + field.component"
:errors="validationErrors"
:resource-id="resourceId"
:resource-name="resourceName"
:field="field"
/></div>
Fields array fills with the data from backend.
So I can see this structure in the Vue dev tool. And when I change the input value it changes value of <form-text-field>, but I don't see this changes anywhere in my Update component.
So my question is - How I can get changes of my input fields dynamically?
In Vue data flows only one way, so the change of data in your Update component will be reflected on form-text-field, but not the other way around. To create 2-way data binding you should use v-model.
I suppose form-text-field is one of your custom components, in that case you should create a custom v-model for it. See: Customizing Component v-model
If you can't get it work post your implementation of form-text-field here, so we can help.
Related
I've got a menu that is visible in the entire website, separated in a section that i call in every layout that i made :
<select class="custom-select">
<option>All categories</option>
<option>Bakery</option>
<option>Fruits</option>
<option>Eggs</option>
<option>Sweets and Chips</option>
<option>hygiene</option>
<option>Kitchenware</option>
</select>
Is there a simpler way to load and fill the options directly from the Blade template instead of calling the controller in every view that i make just to fill the menu?
If this is something you want to use in many different places,you could create a blade component and/or a view composer to load the data.
In my app I want to create a new Risk ( an instance of Risk object ) and when it is created I want to display 5 checkboxes and three radio buttons. Selected options are specific to each instance of Risk object.
Later I want to display a list of all added Risks with an Edit option button on each Risk. I want my app to restore the view specific to a selected Risk ( when an Edit button on a selected risk is clicked ) - with Risk name, all checkboxes and radio-buttons checked as selected previously. And I want to be able to edit these checkbox selections again so that all new changes were properly reflected in MySQL.
As a newbie in Thymeleaf I did the following:
<div th:each="top : ${topic}">
<input type="checkbox" th:field="*{topic}" th:checked="${top.checked}" th:value="${top.name}"/><label th:text="${top.name}">Something is wrong !</label>
</div>
I am sure that Controller and Hibernate/MySQL part works properly ( I checked using Logs ).
This works just fine - but only if I have selected only one checkbox ( initially when I added a risk ).
If I select more than one checkbox (when adding a risk) and later select this risk for editing no checkboxes are checked.
What is wrong ?
After some research I found the following text in Thymeleaf’s documentation:
“… th:field would have taken care of that and would have added a checked="checked" attribute to the corresponding input tags.”.
Also I found this guidance :
http://forum.thymeleaf.org/The-checked-attribute-of-the-checkbox-is-not-set-in-th-each-td3043675.html
Then I managed to develop a couple of small apps and I want to share what I found out and hope it will help someone.
( may be it is too detailed for experienced people, but I want it to be clear to all )
I do not want to repeat what is already in the above-mentioned Thymeleaf’s forum page ( see Administrator’s first response / explanation for detail - second in forum thread ) - just want to make a small summary and stress out few points:
you indeed do not need to add ‘checked’ when using th:each;
you must add th:field=“{…}” which should have the name of the field in your model class (referred by Thymeleaf as form-backing bean - th:object ) to which checkboxes are related. More on this: I stated above that my ‘form-backing bean’ was Risk.java. And for each Risk object instance the selected checkboxes represent topics(s) specific to this Risk instance. And selected topics are assigned to field ‘topic’ of Risk.java's instance (and hence in related table in MySQL when instance is saved). That field’s name should go inside th:field=“{…}” as th:field=“*{topic}” in my case. When you select checkboxes Thymeleaf will save selected values to Risk.java’s topic field using its setTopic method and when it needs to restore view Thymeleaf will use Risk.getTopic method to get info on earlier selected items.
all values of checkboxes (or radio-buttons ) should come from another source - it could be an Enum if you need a static set of checkboxes or if you need checkboxes to be dynamically generated you can use a class ( I needed static set of checkboxes for my app, but I decided to try to create a dynamic one as well - see links to my Github repo’s below to see the code I managed to develop ). So for my app I created an Enum Topics with all values for checkboxes and Enum Types with all values for radio-buttons. Then in your controller class you should add all values to Model’s attribute - I did this as I used an Enum:
model.addAttribute("topics", Topics.values());
model.addAttribute("types", Types.values());
(if you need dynamic ones do the following:
model.addAttribute("topics", topicsService.findAll());
model.addAttribute("types", typesService.findAll());
)
Then you should have something similar to:
<div>
<div th:each="top : ${topics}">
<input type="checkbox" th:field="*{topic}" th:value="${top.id}"/><label th:text=" | ${top.name}|">Something is wrong !</label>
</div>
</div>
<div>
<div th:each="typ : ${types}">
<input type="radio" th:field="*{type}" th:value="${typ.id}"/><label th:text="| ${typ.name} |">Something is wrong !</label>
</div>
</div>
where:
as mentioned, th:field=“{topic}" corresponds to form-backing Model class - Risk.java’s field. Same for th:field=“{type}" ;
topics in th:each="top : ${topics}” should match with attribute name you provided in controller.
And the MOST important part is that th:field=“*{topic}” should return an array.
th:field=“*{topic}” returning an array of selected items and th:each returning array of all options Thymeleaf should now be able to mark checkboxes / radio buttons as checked when values in first array match values in second array.
Since in case of radio buttons you can select only one option th:field=“*{type}” does not actually return an array - it returns only one item. But in case of checkboxes it should be an array - so the ‘topic’ field in Risk.java must return an array.
For this we need a converter - a class named e.g. StringListConverter that implements AttributeConverter….
( I learned how I can do it here. If not this answer in www.stackoverflow.com I would not be able to finalyze this app and would not be writing all this:
https://stackoverflow.com/a/34061723/6332774 )
Then in your form-backing model class - Risk.java in my case you need to do something like :
#Convert(converter = StringListConverter.class)
private List<String> topic = new ArrayList<>();
private String type;
Type can simply be a String.
That is it.
( I wanted to display checkboxes in table form indicating number of columns needed - I could do it, but I am not sure how clean it is or how safe it is. Related code is in riskformtable.html in example project linked below.
I posted a related question here - Thymeleaf - Displaying checkboxes in table form when using th:each - is what I am doing safe?
Also I wanted to use different color for all risk items with even sequential number in my risk’s list - it is in index.html
See full example code using links below )
Links to my GitHub repos:
example with static set of checkboxes : https://github.com/aripovula/Spring-Thymeleaf_checkboxes_and_radiobuttons
example with dynamically generated checkboxes : https://github.com/aripovula/Spring-Thymeleaf_dynamic_checkboxes_n_radio-buttons
I am using Orbeon forms with Hybris. We have several pages linked together where a user needs to go through them in a sequence (checkout process).
The content of the Orbeon form is dynamically being determined based on actions from previous steps. E.g.
If user adds Product A to the cart on the step 1, only two fields will be visible on the form located on step 2, if he adds another (Product B) on step 1, one more field should be visible on the form.
I am using certain preprocessor class which prefills some of the hidden fields on the form and then the logic for dynamic display is on the Form itself, based on those hidden fields. This works in a simple scenario when moving back and forth, through the steps.
However, the problem is that I need to have a HTML Mini-cart displayed on the page as well (not part of Orbeon Form), which can also trigger adding/removing of the products asynchronously.
So while I am on step 2 where the form is displayed, the user can also remove/re-add some of the products -> therefore, this needs to trigger asynchronous re-rendering of the form and change the display of the form (with new fields added or removed).
I'm using AJAX for this async stuff and the problem I am facing is that a lot of Orbeon-specific Javascript files and variables is being generated when the page loads for the first time, and some random FormID is used. This FormID is different when I retrieve the new form from the back-end and when trying to replace the HTML content I'm getting various errors in the console, because old Form id is used all over the place.
Does anyone have any suggestion if this could be achieved and how to approach this problem?
Update: Example of "hidden" field glass-coverage-selected
<xf:instance id=""fr-form-instance"" xxf:exclude-result-prefixes=""#all"">
<form>
<glass-coverage-selected/>
<section-1>
<massive-exterior-walls/>
</section-1>
...
Later, a bind is created:
<xf:bind id=""section-40-bind"" ref=""section-40"" name=""section-40"" relevant=""instance('fr-form-instance')/glass-coverage-selected = 'yes'"">
<xf:bind id=""previous-glass-insurance-bind"" ref=""previous-glass-insurance"" name=""previous-glass-insurance"">
<xf:required id=""validation-156-validation"" value=""true()""/>
</xf:bind>
And that bind is used to control the visibility of certain section:
<fr:section id=""section-40-control"" bind=""section-40-bind"">
<xf:label ref=""$form-resources/section-40/label""/>
<fr:grid>
<xh:tr>
<xh:td>
<xf:select1 id=""previous-glass-insurance-control"" appearance=""full"" bind=""previous-glass-insurance-bind"" class=""previous-insurance"">
<xf:label ref=""$form-resources/previous-glass-insurance/label""/>
<xf:hint ref=""$form-resources/previous-glass-insurance/hint""/>
<xf:help ref=""$form-resources/previous-glass-insurance/help""/>
<xf:alert ref=""$form-resources/previous-glass-insurance/alert[1]"" validation=""validation-156-validation""/>
<xf:alert ref=""$form-resources/previous-glass-insurance/alert[2]""/>
<xf:itemset ref=""$form-resources/previous-glass-insurance/item"">
<xf:label ref=""label""/>
<xf:value ref=""value""/>
<xf:hint ref=""hint""/>
</xf:itemset>
</xf:select1>
</xh:td>
</xh:tr>
</fr:grid>
</fr:section>
You can manipulate the values of form fields in JavaScript, in the browser. If you want to set the value of "hidden fields", you make sure that those fields as not hidden by putting false() under Visibility for the field in Form Builder. If you do this, for security reasons, the value of the field isn't even sent to the browser by Orbeon Forms, and it can't be set from JavaScript. Instead, to be able to set the value from JavaScript, you need to hide the control with CSS. The simplest way to do this is to add the class xforms-disabled for that field in the Control Settings dialog.
Then, assuming the name of the control in Form Builder is my-control, in JavaScript you can write var control = ORBEON.jQuery('*[id $= "my-control-control"]'); ORBEON.xforms.Document.setValue(control.attr('id'), '42');. Note the -control added at the end of the name of the control. And to test this first, I recommend you don't put the CSS class, so you can more easily see if setting the value works.
For the documentation on the above setValue() and other JavaScript APIs, see the page Client-side JavaScript API.
Knockout has the default behavior of updating the associated model if you change your focus (e.g. by clicking outside the input control) after editing the value inside an input control, populated by a binding of type Value.
Here is the link to the official documentation page explanation, section Parameters:
http://knockoutjs.com/documentation/value-binding.html
Do you know a way to disable this default behavior ?
The reason behind this : Im using Models that can tell if their last update requires persistent backup by comparing the previous value to the new one.
I would like to listen to the key up event on my form inputs but if I do that, knockout triggers twice event (the default one + the key up) to update the Model and the second one is basically telling my Model to replace the value by the same value because it is already updated, which it translates to "there is no need to do persistent backup since the value didnt change".
I would gladly appreciate any help or suggestion, since Im stuck and can't find a way around :)
EDIT
Couldnt reproduce the error with bare backbone code. It seems as "super cool" said that valueUpdate should override the default Blur event that triggers when you use form controls with binding Value.
It may be a bug introduced by the library Knockback that I use to create the ViewModel.
Despite all this, just replacing the binding Value by the binding textInput did the trick. Thank you all.
Don't listen to the event, subscribe to updates, which won't fire unless the value is changed. Using the textInput binding will register every change to the value, even those done using menu items like cut and paste, when they happen.
Equivalently, you can use the value binding along with valueUpdate: 'input'
vm = {
myvar: ko.observable(),
updates: ko.observableArray()
};
vm.myvar.subscribe(function(newValue) {
vm.updates.push(newValue);
});
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input data-bind="textInput: myvar" />
<div data-bind="foreach: updates">
<div data-bind="text: $data"></div>
</div>
I've created a sandbox with a demonstration of binding UI components to both data and state: http://dojo-sandbox.net/public/51073/1
It's my plan to generate code from a page definition creating a page-level widget which is templated. This widget will have its own scope, where the model and state will reside, which I am trying to simulate in the sandbox by way of the Page object.
The sandbox is working because the Page object is in the global state, which appears to be the default context for object resolution in mvc binding.
However the plan is to have a view widget supporting each page with both the Model and State contained within the widget's scope. The generated template for the view would be bound to both the Model and the State. I can establish the source via the 'target' property, but when the same UI component must be bound to two different models, one for value and one for state, the single source doesn't support this.
The Model data will come to me from the back-end, and the State data is derived via the State.Execute method once the Model data is present.
I've taken a look at the 'rel:' parameter of at(), but don't see how to leverage this syntax within a specific context, ie my view widget's scope. It seems to be working fine for the default global scope.
Is there a standard way to direct the data-dojo-props value binding at one source, and the data-mvc-bindings for attributes at another? Or, more precisely, what is the at('rel:') syntax which will support specifying the context of the relation, and not rely on the 'target' of the widget or containing widget?
If there is no way to specify the 'target' at this level, I will generate more logic in the Execute method to specifically set the html attribute on the component during state compilation.
data-mvc-bindings is for allowing non-widgets use dojox/mvc/at. If a widget is declared for an element data-dojo-props is the one for use instead.
If target is specified via data-dojo-props or data-mvc-bindings, it’ll be set eventually to the widget.target. ”rel:” syntax looks for a widget having .target up in DOM tree.
It means that one “group” cannot have more than one "relative binding target”, in case it’s one of your questions. You can have a “scope object” that contains pointers to more than one models and use it as a “relative binding target”, that may serve a similar purpose:
<div data-dojo-type="dijit/_WidgetBase"
data-dojo-props="target: {model0: model0, model1: model1}">
<input type="text"
data-dojo-type="dijit/form/TextBox"
data-dojo-props="value: at('rel:model0', 'value'),
disabled: at('rel:model1', 'disabled')" />
</div>
A working example can be found at http://jsfiddle.net/asudoh/M3bRC/. Hope these help.
Best, - Akira