I'm trying to customize the HTML markup of the excellent FilterPane grails plugin, however I'm having some difficulty. FilterPane provides a bunch of tags for rendering the search/filter form, and I would like to override these in my application.
I had thought that I could simply copy the _tagName.gsps that I wanted to override from
plugins/filterpane-2.0.1.1/grails-app/views/filterpane
into
grails-app/views/filterpane
and modify them, however it looks like Grails never checks whether the application is overriding the views of a plugin, if the render method is called with a plugin name property specified.
org.codehaus.groovy.grails.web.pages.GroovyPagesTemplateRenderer.findAndCacheTemplate contains the following code in a private method:
...
GroovyPageScriptSource scriptSource;
if (pluginName == null) {
scriptSource = groovyPageLocator.findTemplateInBinding(templatePath, pageScope);
} else {
scriptSource = groovyPageLocator.findTemplateInBinding(pluginName, templatePath, pageScope);
}
...
so when a non-null pluginName is specified, we just grab the plugin's view and never check whether the application is overriding it.
I thought a simple way to get around this problem would be to just override GrailsConventionGroovyPageLocator.findTemplateInBinding, or some other similar method in GrailsConventionGroovyPageLocator, however it doesn't appear to be possible to do this from within a Grails application either!
I created a simple class overriding GrailsConventionGroovyPageLocator, replacing the findTemplateInBinding method with one that checks the application's view directory before checking that of the plugin. I then modified resources.groovy, adding a doWithSpring closure to replace the beanClass property of the default groovyPageLocator:
def doWithSpring = {
def pageLocator = delegate.getBeanDefinition("groovyPageLocator")
pageLocator.beanClass = MyConventionGroovyPageLocator
}
However this doesn't seem to be called when my application starts up.
I'm really at a loss here. I'd expected this to be straightforward, but it's turned into a bit of a can of worms. Does anyone have any suggestions? All I want to do is override the views provided by a plugin...
You can modify the plugin source, instead of changing the location of the template.
The location is: user_home\.grails\version\projects\project\plugins\plugin-name
I am not a grails expert, but in order to override plugin views you should recreate them in your main projects views folder. For example, I changed the /auth/login.gsp from Spring Security Plugin by simply creating the same thing in my /project/views/auth/login.gsp. If you make changes into the plugin files itself you could potentially lose them if you uninstall the plugin.
In order to change a view in a template of a plugin, perform the command
grails install-templates
source
This will copy the templates of the plugins to your project which you then can customize. What this does with for example the scaffolding plugin, is copy files to src/templates/scaffolding (note, not grails-app/templates/scaffolding). Therefore, in your case, I would try copying the files to src/views/filterpane
Related
Grails 5 is using the fields-plugin (as stated in the scaffolding plugin and I see it in the Intellij-IDEA Grails-View of my project under plugins).
But how can I install the fields-plugin templates?
Even in the GitHub-sources I could only find the templates for _embedded, _list and _table.
what am I missing?
(The reason for all that is, that I want to know, how the inList constraint is handled in a g:select. I know it's working, but if I try it the "old-fashioned" way with
from=${MyDomain.constraints.myField.inList}
grails throws errors Cannot get property 'myField' on null object
Please correct me if I'm wrong, but the delivered plugin has no other template files as the mentioned ones, the base "template" is done through the taglib and you can override with "self-made" tag-gsps in views.
But I would like to see some documentation, which variables you could use in own template-files... or did I miss it?
The constraints attribute has changed to constrainedProperties.
I'm trying to write a grails plugin that can view files. Actually, I'm just trying to upgrade this one here... https://github.com/intelligrape/File-Viewer-Grails-Plugin to grails4, and get it working in my app.
Anyway, after I get it working in the app, I visit http://localhost:8080/file/index and I get this error:
URI
/file/index
Class
javax.servlet.ServletException
Message
Could not resolve view with name '/plugins/file-explorer-0.1/file/fileList' in servlet with name 'grailsDispatcherServlet'
This occurs when the controller does this...
def index(String filePath) {
Map model = [locations: fileLocations.locations]
// blah blah
render(view: "/file/fileList", model: model, plugin: 'fileExplorer')
}
The render() method is called (I checked in the debugger). I also tried removing the plugin: parameter, but it made no difference.
Now if I run the plugin as a standalone app (by going to that folder, and running "grails run-app", then it works as expected, and http://localhost:8080/file/index renders the view as one would expect.
This all leads me to believe that the plugin is basicly working and installed into my app EXCEPT the view component, which for whatever reason cannot find the views from a plugin.
If you want to know what the source looks like, it's basically what you see here:.. https://github.com/intelligrape/File-Viewer-Grails-Plugin Except I've renamed it from FileViewer to FileExplorer.
I'm using grails 4.1.0.M5 I don't know if it could be a bug in this version or what.
It seems that I should have had
plugin: 'filexplorer'
instead of
plugin: 'fileExplorer'
I could have sworn I tried this already. I guess the thing is it can be confusing which name to use where as far as plugins, as in the build.gradle name, the name in the *Plugin.groovy, the name in settings.gradle, the package name etc. Anyway, somehow I screwed up.
We use Weceem, which uses loadBefore inside of WeceemGrailsPlugin like this:
def loadBefore = ['controllers', 'ckeditor', 'elasticsearch']
What happens is, WeceemGrailsPlugin gets processed, then our application's resources.groovy, then ElasticsearchGrailsPlugin gets processed after that.
The problem is, I need to override one of the beans in elasticsearch inside our app's resources.groovy, so I need it to process the ElasticsearchGrailsPlugin doWithSpring block before our resources.groovy.
Is there any way to force that behavior in resources.groovy somehow? Some kind of 'loadAfter' capability we could use to force it to load elasticsearch first, or another workaround to force it?
I am working on a multi-tenant architecture based plugin, where I am adding a tenantId variable on few domain classes. Now this variable gets assigned its value automatically at object creation time via some code in Domain class itself and the User need not assign it manually.
Now the problem is that I need to provide this functionality to other developers and who actually generate the GSP views using grails generate-views com.something.someClass.
By doing this the generated view also has field for selection of tenant. So is there any domain class constraint or any setting that I can apply to prevent this variable from being automatically included in the view?
P.S. - Any such setting will be anytime better than manual removal of field from view each time.
Thanks.
Try follow steps:
1- run this command to copies the the templates used by Grails during code generation
grails install-templates
2- then open _form file (found in src/templates/scaffolding folder)
3- add tenantId in excludedProps variable like grails did with version field
excludedProps = Event.allEvents.toList() << 'version' << ... << 'tenantId'
Note- I haven't tried this.
When I create a RESTful API in Grails, I add #Resource(uri='env',formats=['multipart/form-data'] before the domain class. And then use grails generate-all domain_name to generate the controller and view.
However, in Eclipse there is an Java problem like
The project was not built due to "RequestEnvironmentController$_on_closure51 [in [Working copy] RequestEnvironment.groovy [in test.environment.manager [in grails-app/domain [in restful-api-for-tem]]]] does not exist". Fix the problem, then try refreshing this project and building it since it may be inconsistent.
Then I get rid of the annotation and the error disappears and the post method still works. I am confused, is the annotation necessary or not? If it is necessary, how can I remove the Java error?
When you use the #Resource annotation there is no need to create a controller because this will be automatically generated as per documentation
Simply by adding the Resource transformation and specifying a URI,
your domain class will automatically be available as a REST resource
in either XML or JSON formats. The transformation will automatically
register the necessary RESTful URL mapping and create a controller
called BookController.