I would like to use:
<core:Icon src="{path: 'STATUS', formatter: '.formatter.getTableStatusIcon'}" />
But I get this error when I use it:
Element sap.ui.core.Icon#__icon0-__clone600: Property 'src' (value: '') should be a valid Icon URI (sap-icon://...)
Instead of an empty string, return null.
getTableStatusIcon: function(status) {
// ...
return null; // default value of the Icon src
},
Or in case of an expression binding in XML view:
<core:Icon src="{= <my condition> ? ${myIconUri} : null}" />
This won't trigger the assert message because null and undefined are used for resetting Control's property value (i.e.: no icon), which I assume you were trying to do by passing an empty string.
The message was first introduced in 1.56 in order to discourage developers from assigning the icon name only (e.g. "edit" instead of "sap-icon://edit"):
Although it is not mentioned in the API, the 'src' property also
accepted a[n] icon name of the default collection as value instead of the
documented Icon URI (IconPool.getIconURI).
This is was caused by 867c4c6 and works
again, but is still not recommended. Therefore an assertion is added. (Source)
Related
In my JSX code I have attribute name that has colon in its name but vscode shows error. Even after formatting my code, vscode automatically create a space after colon. How to solve these two problems?
By not having colon in your attribute name. While technically possible, attribute names should be camelCase.
If you can't get around this, you could create and object and destructure it onto props.
const A = () => {
const fooProps = {
'on:resize': onResize
}
return <Foo {...fooProps} />
}
\Templates\Snippets\Search.html
<f:form id="snippetSearchForm"
action="search"
controller="Snippets"
extensionName="snippet_highlight_syntax"
pluginName="feshs"
name="searchSnippets"
method="POST"
pageType="5513">
<f:form.textfield class="form-control" property="searchWords"/>
<f:form.submit id="searchBtn" value="Search"/>
</f:form>
SnippetsController.php
public function searchAction()
{
$arguments = $this->request->getArguments();
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($arguments);
}
ajax.js
$("#snippetSearchForm").submit(function (event) {
event.preventDefault();
var form = $(this);
var action = form.attr("action"),
method = form.attr("method"),
data = form.serialize();
$.ajax({
url: action,
type: method,
data: data,
cache: false
}).done(function (data) {
console.log(data);
}).fail(function () {
( "div.tx-feshs" ).replaceWith("errorMessage");
}).always(function () {
});
});
Request URL
index.php?id=148&type=5513&tx_snippet_highlight_syntax_feshs[action]=search&tx_snippet_highlight_syntax_feshs[controller]=Snippets&cHash=4662b6b5a3fa0dc4e590e8d5c90fa
I can't solve this problem with getArguments(). The response and console.log are (empty). Seems like I'm missing something but I can't pinpoint where :/
You have a few common errors in your code and most of them has already been mentioned here, but please allow me to sum up.
Extension key/name
First, a lot of people confuses extension name with extension key. The directory name of your extension is your extension key, in this case snippet_highlight_syntax. The extension key is used all over TYPO3 as the unique identifier of your extension. With Extbase a new convention did come along called extension name to satisfy PSR2 coding convention and is primarily used in Extbase context. The extension name is a upper camel case edition of your extension key.
ExtbaseFluidBook: CodingGuidelines - It´s a bid old but still valid
The name of the extension in UpperCamelCase. For example, if the extension-key is blog_example, then this part of the classname is BlogExample.
Extension key: snippet_highlight_syntax
Extension name: SnippetHighlightSyntax
Be aware of what the TYPO3/Extbase framework asks for, key or name - it will help you a lot.
Plugin name
You have also declared a plugin named feshs. According to the DocBlock documentation of both \TYPO3\CMS\Extbase\Utility\ExtensionUtility::(configure|register)Plugin() methods it should, as with the extension name, be in upper camel case format like Feshs. It´s not well documented and I do not think it has any negative impacted on your application jet but now you knows and has a change to future proof your application by correcting it.
/**
* ...
*
* #param string $extensionName The extension name (in UpperCamelCase) or the extension key (in lower_underscore)
* #param string $pluginName must be a unique id for your plugin in UpperCamelCase (the string length of the extension key added to the length of the plugin name should be less than 32!)
* #param array $controllerActions is an array of allowed combinations of controller and action stored in an array (controller name as key and a comma separated list of action names as value, the first controller and its first action is chosen as default)
* #param array $nonCacheableControllerActions is an optional array of controller name and action names which should not be cached (array as defined in $controllerActions)
* #param string $pluginType either \TYPO3\CMS\Extbase\Utility\ExtensionUtility::PLUGIN_TYPE_PLUGIN (default) or \TYPO3\CMS\Extbase\Utility\ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT
* #throws \InvalidArgumentException
*/
public static function configurePlugin($extensionName, $pluginName, array $controllerActions, array $nonCacheableControllerActions = [], $pluginType = self::PLUGIN_TYPE_PLUGIN)
Plugin signature
Together with your extension name it will form a plugin signature called snippethighlightsyntax_feshs. This signature is the valued stored in the tt_content database table as list_type or ctype depending of the plugin configuration.
The plugin signature is further used in TypoScript and GET/POST arguments prefixed with tx_. In your case tx_snippethighlightsyntax_feshs.
Fluid & Extbase forms
In your form snippet you have declared a element <f:form:textfield /> with the property tag. The property tag is only used together with the object and objectName tags on the <f:form /> element and is used to bind values to this objects properties (autofill, validation result etc.).
See \TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper::initializeArguments.
Name of Object Property. If used in conjunction with <f:form object="...">, "name" and "value" properties will be ignored.
In your case you should properly just use name in stead of property.
Your updated form should look something like below:
<f:form id="snippetSearchForm"
action="search"
controller="Snippets"
extensionName="SnippetHighlightSyntax"
pluginName="Feshs"
method="POST"
pageType="5513">
<f:form.textfield class="form-control" name="searchWords"/>
<f:form.submit id="searchBtn" value="Search"/>
</f:form>
Controller arguments
You should declare your arguments as controller arguments.
/**
* #param string $searchWords
*/
public function searchAction(string $searchWords = null)
{
if (is_string($searchWords)) {
// TODO: Do something here...
}
}
Note how I have given the argument a default value. This should suppress the error Required argument "searchWords" is not set for... you are getting.
This was a long write up. Hopes it helps your or some others.
Happy coding
$this->request->getArguments() will only return field value arguments that are prefixed with the extensions / plugins identifier like tx_anything_pi1[anything]
Please checkout if the "name"-tag of the fields is correct. Maybe those tags are wrong because you are reffering to a "property" of an object in your textfield but there is no object bound to your f:form tag.
Since the response should at least return the HTML of an empty debug, maybe something is wrong with your action. Can you call it in the browser?
First of all use name attribute instead of property in <f:form.textfield> tag.
Then you need to register argument as follows
public function searchAction(string $searchWords)
Furthermore PHP docblock must contain the parameter as #param string $searchWords. After clearing all caches in the Install Tool you should get your arguments.
Assumed your extension-key (=foldername) is "snippet_highlight_syntax" the parameter for URLs is usually like this:
tx_snippethighlightsyntax_feshs
That means all underscores of the extension-key are removed.
Probably it's possible to make it different, but that's not standard.
Therefore $this->request->getArguments() never returns anything.
You've to adjust the parameters in the url like this:
index.php?id=148&type=5513&tx_snippethighlightsyntax_feshs[action]=search&tx_snippethighlightsyntax_feshs[controller]=Snippets&cHash=4662b6b5a3fa0dc4e590e8d5c90fa
In the TypoScript-Object-Browser you should find your plugin with that name:
plugin.tx_snippethighlightsyntax_feshs
After many tries, I've sent the extension to test on another computer and it's working.
I've cleared all the caches, disabled/enabled, and so on. Seems like my environment is at fault.
Thanks to all of you for the help !
I have a "Thing" domain class, where each Thing has an record number (which is not the automatically generated id), that the user will use to access a Thing:
class Thing {
...
String recordNumber
...
}
There is a form to look for a Thing, knowing its recordNumber:
<g:form action="search">
<input name="recordNumber">
<g:submitButton name="btn" value="go to this Thing"/>
</g:form>
I would like to use a validation process in this form: if the recordNumber is not found (Thing.findByRecordNumber(recordNumber) == null), then the input field must turn in red, and a tooltip must show the error message "record number not found".
As far as I know/read (I'm a grails rookie), this has to be written as a constraint in the Thing class:
static constraints = {
recordNumber validator: { n -> Thing.findByRecordNumber(recordNumber) }
}
The problem is: I do not have in this form all the "Thing" properties to populate, just the recordNumber one, so I just can't call
new Thing(params).validate()
How to call validation on just one field, not on the whole object ?
If this is your main question, although I see others there:
"How to call validation on just one field, not on the whole object ?"
You can pass a list of values to validate and it will only validate those properties
new Thing(params).validate(["recordNumber"])
http://grails.org/doc/latest/ref/Domain%20Classes/validate.html
Validation is for constraints for domain class properties. You need an action in your controller:
def search = {
if(params.recordNumber && Thing.findByRecordNumber(params.recordNumber)){
redirect(action: "show", params:[id:Thing.findByRecordNumber(params.recordNumber).id])
}else{
flush.message = "No record found"
render(view:'VIEW_WITH_SEARCH_FORM')
}
}
If you want to validate without refreshing page, write a javascript code.
I am using rich faces select component.
I want dynamic values when user manually type some thing in the select component.
<rich:select enableManualInput="true" defaultLabel="start typing for select" value="#{supplierSearchBean.userInput}">
<a4j:ajax event="keyup" execute="#this" listener="#{supplierSearchBean.userInputChange}"/>
<f:selectItems value="#{supplierSearchBean.selectOptions}" />
</rich:select>
Java code as follows
public void userInputChange(ActionEvent ae){
Map map = ae.getComponent().getAttributes();
System.out.println(map.toString());
}
public void setUserInput(String userInput) {
System.out.println("userINput = " + userInput);
this.userInput = userInput;
}
Here i found 2 issues
1st: setUserINput always print empty string when user type value
2nd: listener method never get call.
any help ?
The problem is most probably that there is no selected value while the user types, and this component restricts the allowed values to the specified select items. A partial input is thus not valid and cannot be bound to your bean.
I think you could get the expected behavior if you use a rich:autocomplete instead. However, if you want to restrict the allowed values, maybe you can keep your rich:select and listen for the selectitem event.
Override getItems function in richfaces-utils.js file in richfaces-core-impl-4.0.0.Final.jar under richfaces-core-impl-4.0.0.Final\META-INF\resources folder.
Change the condition of pushing items to be
if(p != -1)
instead of
if(p == 0)
This should fix the issue.
I'm working on single page application, which involves sorting.
I use
viewModel = new {
SortAsc = ko.observable(true)
};
ko.linkObservableToUrl(viewModel.SortAsc, "Asc", viewModel.SortAsc());
to achieve that mapping. And it works, but the problem is that mapping returns literal strings "false" and "true" instead of bool value. This causes a problem with checkbox, which is bound to that property:
<input type="checkbox" data-bind="checked: SortAsc" value="Ascending"/>
The question is, how can I make that value from url to be converted to correct type (normal bool), so my checkbox will be updated properly?
Ok, I found how to overcome that problem. Not very elegant, but works.
1. I assumed, that SortAsc will be a string property in my logic. So I left it bound to url like in the question text. Only initialized it with string, istead of bool ("true" intead of true).
2. I created writeable dependend observable, which will do the convertion:
viewModel.SortAscBool = ko.dependentObservable({
read: function () {
return this.SortAsc() === "true";
},
write: function (value) {
this.SortAsc(String(value));
},
owner: viewModel
});
and bound my checkbox to that prop. So now, when checkbox is checked, SortAscBool is changed and it sets literal value to SortAsc (I think this convertion is really not needed, but as a C# programmer I like it that way :)). And of course, when SortAsc changes, SortAscBool will also change and return the converted value to checked binding. And that is what was really needed.
Also, my first though was to simply create one way dependend observable, but then url will not be updated with values from checkbox.