How can I include a script defined in Theme to a view from Modules in Orchard

Topics: Core, Customizing Orchard, General, Writing modules, Writing themes
Jan 11, 2013 at 6:25 PM

I define styles for all different modules in theme. Each CSS file belongs to a certain module. Only theme knows which file is that. I want my view in module to include (via Require) a style defined in Theme via Style.Require. How can I do that in Orchard?

Jan 11, 2013 at 9:38 PM

Unless I misunderstood what you're doing, I would strongly advise against that setup: you should not want to have your module's views "know" about resources from a theme.

Instead, you should provide default styles as part of your modules and use those, and override your module's views in your theme, from which you can include theme specific styles.

Jan 11, 2013 at 11:52 PM

There are 2 problems with your suggestion.

First - I dont want to fight the default module styles overriding them from the theme, what I want is that my theme just give the module the right resource that the module could link as if it was its own. So in a way I want my module to keep the design question open to be answered by the theme when it comes into play.

Second. Actually, I can achieve this by not linking any css files in the module yet using CSS classes in the HTML markup in its view. These classes will be defined in the theme later. The problem with this is that I have to load all styles for all modules as a single CSS file, because the theme doesnt know what particular CSS file is right for a given module. Unless I redefine the module's view in the theme, but it seems like an overkill just to link one file.

Jan 12, 2013 at 12:10 AM

Speaking of the module knowing about resources defined in the theme. No, the module doesn't know the exact names of the resource files, instead it requests them indirectly using something similar to resource manifests that are defined in the theme and required in the module using some key that would get resolved to a real file according to the implementation of the theme.

Jan 12, 2013 at 8:10 AM

I'm not sure how that would be fighting the default module styles, since Orchard is designed to make template overriding very easy.

Anyway, if you must, you can always include a CSS in your module's views by using the full path, e.g. [~/themes/mytheme/styles/module1.css] using the [Style.Include] method.

Although I never tried it (and I never will), but you could probably also define a ResourceManifest in your theme and expose your styles as resources. Then you should be able to use the [Style.Require] method from within the views of your module.

Your last post suggests you already found a solution?

Jan 12, 2013 at 1:18 PM
Edited Jan 12, 2013 at 1:39 PM

No. Unfortunately registring a style in the resource manifest in a theme and then referring to it in the module doesn't work apparently because the have different manifests at the very least.

There is a workaround that I outlined earlier but I don't like it because it requires overriding views just for the sake of resolving one CSS file. 

Unless there is some mechanism that works this situation out gracefully, I think it is a searious flaw in Orchard's design being not able to allow theme to resolve references to resources for a module.

 

I opened an issue regarding this problem http://orchard.codeplex.com/workitem/19394

Jan 12, 2013 at 1:45 PM
middlewest wrote:

Unless there is some mechanism that works this situation out gracefully, I think it is a searious flaw in Orchard's design being not able to allow the theme to resolve references to resources for a module.


A Theme is able to include resources that are exposed by modules.
The other way around is possible as well, but this is generally not the way to do it. So lack of support of that approach is imho not a flaw in design, but rather a good way to promote good practices and discourage bad practices.
It doesn't mean you can't do it though. As I mentioned previously, you can use the "Style.Include" method if you really must.

Please let me explain why I regard it a bad practice:

Modules are designed to be usable by any theme, therefore they should not rely on Theme specific stuff such as styles.
Instead, Modules can be accompanied with their own CSS to provide a default look and feel.
Most developers will ship their modules with views that contain CSS classes that exist in TheThemeMachine, since that's the default theme.
This is fine. When you create your own theme, you can of course completely create theme specific CSS.
And it's very common to override the views from a module in a theme.

In your case, if you really must reference styles from your theme from within your module's views, you may as well store these stylesheets in the Styles folder of your module directly.

I may be misunderstanding the issue of course. If you feel that I do, please provide us with an example that clearly shows the issue.

Jan 12, 2013 at 2:06 PM
Edited Jan 12, 2013 at 2:08 PM

Here is our situation.

We have chosen Orchard as a platform for our product. The product takes advantage of the existing standard modules (blogs, forums, cms) and provides something of its own value. So we design the parts of our product as modules. There is a default theme that represents our company identity. The set of styles is quite complex. There are about 15 modules that we already built. The problem with the default styles for each module is that we have to maintain 15 identical sets of styles that are essentially the same for each module that have them as a part of itself. See?

 

In our particular situation we have full control over how these modules are shipped. So we say that in order save some effort we maintain only one default theme that is shipped with all 15 modules as a single product. All we need to do now is to allow a module to link the right CSS file from it. And this is where Orchard falls short.

Jan 12, 2013 at 2:24 PM
Edited Jan 12, 2013 at 2:25 PM

I see. Actually, I have a similar situation, where I use both existing standard modules as well as a bunch of custom modules and a single, custom theme, where I don't want to maintain duplicate stylesheets and sprites.

The way I approached this is by having each custom module its own set of (sub) styles. So the "global" styling such as master layout, fonts, etc. is stored in CSS files in the theme, and the "local" styling such as the layout of a custom piece of UI provided by one of the modules is stored in CSS files in that module.

As for the styling of the standard modules, that is all done as part of the custom theme.

One challenge I had at some point was how to deal with sprite image files that contains sprites required both by the Theme as well as some of the stylesheets of the modules. I solved this one by simply reorganizing my sprite sheets and styles.

Another approach that will definitely work is by providing a "common" module that exposes all of the required resources, made available to all of your modules and the theme. Each module would have a dependency on this "resource provider" if you will. This setup enables each view in every module to selectively Include or Require a resource.

Problem solved. This is where Orchard shines.

Jan 12, 2013 at 2:45 PM
Edited Jan 12, 2013 at 2:50 PM

What you suggested is to have a theme referenced by a module. Well this is what looks like a brutal violation to me.

I agreed that the approach with having placeholder classes (to be defined later in the theme) and some styles in the module could work. But it's a half-baked solution:

-Who decides which classes to be kept in the module and which ones to be stubbed? What are the considirations that drive this decision?

-when you override an exising CSS you have to carefully mimic the hierarchy of nested classes/elements in order to target the right property on a right element. In case the original CSS has some structural changes odds are your overrides will be off. This is a source of headache.

- all in all why would I bother with all this when the best solution in my particular case is to just make a theme provide a right resource to a module?

Jan 12, 2013 at 3:21 PM

That's not at all what I suggested. I think we're misunderstanding each other. To me it sounds like you're contradicting yourself:

A. "What you suggested is to have a theme referenced by a module. Well this is what looks like a brutal violation to me." -> exactly, that's my whole point. Don't do this.
B. "all in all why would I bother with all this when the best solution in my particular case is to just make a theme provide a right resource to a module?" -> Doesn't this mean having a module that references stuff from your theme, hence undergoing a brutal violation?

Having a theme referenced by a module (hence having a theme as a dependency of a module) is indeed a brutal violation, which is the point I'm trying to make. So I am glad we can at least agree on that :)

So let me clarify what I DID suggest:

- Create a common module (not a theme) that provides all the resources that your other modules need. I agree it's not pretty, and it does feel like a theme in a sense, but it is definitely not a theme. It is a "resource provider", just like Orchard.jQuery is, but at least your not violating anything.

Frankly, I fail to see your point where Orchard fails and what the exact issue is. I understand your setup, but I do not see the problem. Sorry.

Jan 12, 2013 at 3:57 PM
Edited Jan 12, 2013 at 4:13 PM

What you call a "common module" is essentially a theme implemented in form of a module that is referred from another module. This is where my objection is when I say I don't think it is a good idea.

Contrary what I suggest is for a module to have some mechanism to delegate resolving links to concrete resources to somebody outside of that module (a theme for example).

It can be done by somewhat similar to a resourse manifest defined in a theme, but used in the module. Or if you will, a module can create a blank manifest and expose it to a theme, so that the theme could populate it with the resolved resources.

My point is that 1. It would be very nice to have for situations like mine. 2. It seems that there is no alternative in Orchard because either it's not the way to use it (fine give me something that works in my situation as well) or if my concern is valid  then it is a flaw in Orchards design that can be addressed in feature releases.

Jan 14, 2013 at 6:14 AM
Edited Jan 14, 2013 at 6:15 AM

Although I honestly like skywalker's solution better, it's not hard to override a module's resource manifest.  Just make sure you create your theme in it's own project.  You can do this from the command line...

codegen Theme ThemeName /CreateProject:true

Now, just add a new resource manifest to your project that overrides the one you want to change...

[OrchardSuppressDependency("Orchard.jQuery.ResourceManifest")]
    public class ResourceManifest : IResourceManifestProvider {        
        public void BuildManifests(ResourceManifestBuilder builder) {
            var manifest = builder.Add();
            manifest.DefineScript("jQuery")
                    .SetUrl("http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.2.min.js")
                    .SetVersion("1.8.2");          
            //and so on 
    }
}  

Now when a module uses Script.Require("jQuery"), it will use the location you've provided over the one in the module. I just tested to be sure it works. It seems like backwards thinking to me, but you can definitely do it if you want.

Jan 14, 2013 at 12:18 PM
Edited Jan 14, 2013 at 1:21 PM

This is almost what I am looking for.

Problem is that OrchardSuppressDependency cancels all the default references in the original module. Which leaves me no choice but to redeclare whatever was cancelled in addition to the overrides of the styles that I need to fix. Which is something I don't want to do because god knows what was there and I am not supposed to know this. So all in all this approach doesn't work either.

Jan 14, 2013 at 7:50 PM
middlewest wrote:

Which is something I don't want to do because god knows what was there and I am not supposed to know this. 

Which is precisely why I agree with skywalker that this whole approach is backwards to begin with.  Just my opinion though.  Hope you find something that works for you.

Jan 15, 2013 at 3:50 AM
Edited Jan 15, 2013 at 3:51 AM

Hey. I am getting tired if you saying backwards. What is there so backwards in overriding the entire CSS file rather than doing it style-by-style which is what you would refer to as straight forward?

Jan 15, 2013 at 4:08 AM
Edited Jan 15, 2013 at 4:39 AM

Ya, backwards probably isn't the right word.  Just weird to me.  Just sharing my opinion and trying to help.  

Are these modules ones that you wrote?  Typically modules have very little CSS, so I'm just wondering. 

Oct 25, 2013 at 12:01 AM
Thank you @BrandonJoyce, your solution worked for me!