Access component from custom validator in Angular2 - forms

I'm writing a custom validator for a custom form component in Angular2.
Right now, i can inject dependencies in my custom validator such as services.
But i need to have access from the validator to informations stored in the Component...
So i'm trying to inject the component in the Validator class, but this does not work..
I think i'm missing something with DI !
Look at this plunker here
When you open it, everything should work fine.
Uncomment everything in the validator constructor, like this:
constructor( private test: TestService, private component: CustomFormControlComponent ) {
test.serviceMethod();
component.componentMethod();
}
And check the log output to see that DI failed to resolve the second parameter ...
Any idea why ?
Thanks a lot !

Related

Custom Form Layout Validation

I want to have my own validation flow, with custom layout and message.
By default, the validation from the form builder put all the error message beside the input field. And it will validate all fields at once after submit.
I want to validate field by field after submitting, and error message is displayed in the same place for all the input fields (beside the submit button/on top of the form).
Currently I'm trying custom form layout with "ASCX" type. Is it possible to do all the validation in the back-end code ".cs"?
Or I must inject java script at the custom form layout design in source mode?
Or there is any better way to do it?
In HTML layout type you can place validation macros anywhere you need -> $$validation:FirstName$$
You can also specify a validation that executes without submitting the form - example -> http://devnet.kentico.com/articles/tweaking-kentico-(2)-unique-fields
Anyway, with the validation macro above you can move the error message wherever you want.
In your online form, go to Layout and enter your layout markup manually using HTML and the macros for form field values, labels and validation. There you can specify where all your form elements will go on the form, even the button.
If you want to have custom CS for your validation of that form, you're better off creating a custom event handler for the form before insert. See documentation below:
Custom event handler
Form Event handler
using CMS;
using CMS.DataEngine;
using CMS.OnlineForms;
using CMS.Helpers;
// Registers the custom module into the system
[assembly: RegisterModule(typeof(CustomFormModule))]
public class CustomFormModule : Module
{
// Module class constructor, the system registers the module under the name "CustomForms"
public CustomFormModule()
: base("CustomForms")
{
}
// Contains initialization code that is executed when the application starts
protected override void OnInit()
{
base.OnInit();
// Assigns a handler to the Insert.After event
// This event occurs after the creation of every new form submission
BizFormItemEvents.Insert.After += Insert_After;
}
private void Insert_After(object sender, CMS.OnlineForms.BizFormItemEventArgs e)
{
if (e.Item.TypeInfo.ObjectType.ToLower().Contains("bizform.codename"))
{
//do some work or form validation
}
}
}

Typo3 Extension PHP View

Using the infos in this link:
https://docs.typo3.org/typo3cms/ExtbaseFluidBook/8-Fluid/9-using-php-based-views.html
I try to create an action to output a JSON.
I have a normal controller with the list action:
public function listAction()
{
$storelocators = $this->storelocatorRepository->findAll();
$this->view->assign('storelocators', $storelocators);
}
And in ext/my_storelocator/Classes/View/Storelocator I have a class List.php:
<?
class Tx_MyStorelocator_View_Storelocator_List extends Tx_Extbase_MVC_View_AbstractView {
public function render() {
return 'Hello World';
}
}
All I get is:
Sorry, the requested view was not found.
The technical reason is: No template was found. View could not be resolved for action "list" in class "My\MyStorelocator\Controller\StorelocatorController".
So I guess there is something wrong with the paths. Or where is the Problem?
Edit: Extensioninfos
Vendor: My
key: my_storelocator
controller: NOT SURE (I created it with the extension_builder so I guess my controllers name is Storelocator)
action: list
From my understanding a classname like Tx_MyStorelocator_View_Storelocator_List should be correct. But its not working
You will need to create an empty file for the HTML view for your controller, e.g. Resources/Private/Template/Storelocator/List.html, even if you do not plan to use the HTML view or if you just return the content yourself (which is perfectly fine).
The reason for this is simply technical limitation.
First of all, TYPO3 now has a built-in JSON view, described thoroughly here: https://usetypo3.com/json-view.html. It lets you easily define which properties you'd like to render.
The error message means that your Controller is still pointing to the TemplateView - because thats the error the TemplateView throws if it can't find the defined template file.
You can specify which view to use to render within your controller. You can either set a default view via the $defaultViewObjectName property, like so:
/**
* #var string
*/
protected $defaultViewObjectName = '\TYPO3\CMS\Fluid\View\TemplateView';
You can also set it from within the Controller inside initialization actions like so:
public function initializeExportPDFAction(){
$this->defaultViewObjectName = 'Vendor\Extension\View\FileTransferView';
}
(I have, however, not yet found a way to define the template from within actions, any tips in the comments would be appreciated)
Your path syntax is probably out of date. Instead of writing a render() function in Classes/View/Storelocator/List.php, try writing a listAction() function in a Classes/Controller/StorelocatorController.php file. Extension Builder should have created this file for you, if you made an aggregate model with the usual "list, create, edit ..." and such actions.
Review A journey through the Blog Example and the following chapter, Creating a first extension, for tips.
Keep in mind that there is a mismatch between the documentation and the Extension Builder generated PHP code files. Developing TYPO3 Extensions with Extbase and Fluid has some parts up to date, and other parts still using old syntax.

querySelect angular component as MyComponent

I have an angular component
<my-component foo="" bar=""></my-component>
And its corresponding class MyComponent
I use this component in my html
<my-component foo="bar" bar="foo"></my-component>
<my-component foo="baz" bar="qux"></my-component>
<my-component foo="bar" bar="baz"></my-component>
Now i want to querySelect my custom elements and access their attributes directly. I think about something like this:
List<MyComponent> mys = querySelector('my-component');
mys.forEach((my){
print(my.foo);
my.bar = '1234';
});
There are a view problems with that code:
querySelector always returns Element not MyComponent. can i cast Element to MyComponent?
Is MyComponent to <my-component> like DivElement to <div>?
querySelector cannot select custom elements. i could ad a class to every my-component and select it with that class. or is there another way?
I only can access the attributes with my.getAttribute() not with my.foo. I know, this is because my is still a Element not a MyComponent.
This is not officially supported. There was something like ng-element that allowed this as far as I remember but was intended to be only used for unit tests. There were some changes in the last versions but I don't know the current state.
You should pass references using dependency injection, Angular events (explained here How to communicate between Angular DART controllers) or the scope to access other elements.

Wicket 1.5 - EmailTextField: accept "plus" symbol

I'm using a EmailTextField in a wicket 1.5 app in order to log users. According to GMail alias, a + symbol may be present in email but wicket doesn't allow it. Is there a way to accept extra symbol in the validator?
You have to write your own validator:
public class GMailAddressValidator extends PatternValidator {
public GMailAddressValidator() {
super("^[_A-Za-z0-9-+]+(\\.[_A-Za-z0-9-+]+)*#[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*((\\.[A-Za-z]{2,}){1}$)",
Pattern.CASE_INSENSITIVE);
}
}
Here I just add two pluses to original Wicket regexp for validating e-mails (tried to highlight pluses in bold):
^[_A-Za-z0-9-+]+(\\.[_A-Za-z0-9-+]+)*#[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*((\\.[A-Za-z]{2,}){1}$)
After that you could use simple TextField with your validator instead of EmailTextField. Like that:
new TextField<String>("email").add(new GMailAddressValidator())
I think you will have to override the HTML5 validation like this: Override html5 validation, the component only sets the input type to email, i dont think it adds any wicket validation. If you dont want to add the js override, the best thing todo would be to create your own validator for a wicket TextField.

How to remove a validator from a Select?

I have a form where I need to add/remove validators dynamically. Based on a dropdown selection, other form fields may have different validation rules.
For other kinds of inputs, I've used replace(methodThatCreatesTheInput()) to get rid of a previously added validator. (Not knowing of a better way. Specifically, there doesn't seem to be any way to directly remove a validator from a component...)
With Select, from wicket-extensions, this approach fails with something like:
WicketMessage: submitted http post value [[Ljava.lang.String;#5b4bf56d]
for SelectOption component [8:myForm:targetInput] contains an
illegal relative path element [targetConsortiums:1:option] which does not
point to an SelectOption component. Due to this the Select component cannot
resolve the selected SelectOption component pointed to by the illegal value.
A possible reason is that component hierarchy changed between rendering and
form submission.
The method that creates the Select:
private FormComponent<?> targetSelection() {
Map<Class<? extends Target>, List<Target>> targets = targetService.getAllAsMap();
SelectOptions<Target> propertyOptions = new SelectOptions<Target>("targetConsortiums",
targets.get(Consortium.class), new TargetRenderer());
SelectOptions<Target> consortiumOptions = new SelectOptions<Target>("targetProperties",
targets.get(Property.class), new TargetRenderer());
Select select = new Select(ID_TARGET, new PropertyModel<Target>(model, "target"));
select.add(propertyOptions);
select.add(consortiumOptions);
select.setRequired(true);
select.setMarkupId(ID_TARGET);
return select;
}
(Why use a Select instead of normal DropDownChoice? We want the two types of choices to be clearly separated, as documented in this question.)
Any ideas how to solve this? What I'm trying to achieve is, of course, very simple. Unfortunately Wicket disagrees, or I'm using it wrong.
Wicket 1.4.
I don't know how to do this on Wicket 1.4, but on Wicket 1.5 there is a remove method for validators on FormComponent (see javadoc)