I've tried to use this code in my .NET 5 Blazor project, in .razor file:
<SignedLabel class="some-css-class" Price=123 Currency=Currency.Usd />
where SignedLabel - is a Blazor component and Price, Currency is the component's input parameters. I expect Blazor to treat the class word as an html property and apply the plain HTML class to this component so that I can style this component later on. But Blazor actually treats it as another input parameter for component and crashes whole app rendering with error:
Object of type 'SignedLabel' does not have a property matching the name 'class'
So the questions is
Is it possible to use the class property in a such way?
If yes, how should I do this?
PS: project settings:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>9</LangVersion>
</PropertyGroup>
...
</Project >
You cannot apply a class to a Component. You can use splatting to capture attributes placed on a Component to pass as parameter to one of the components elements.
SomeComponent.razor
<div #attributes="#CapturedAttributes">
Hello
</div>
#code {
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string,object> CapturedAttributes { get; set; }
}
##Usage
<SomeComponent id="fred" class="some-css-class" style="width:100vh" />
Will render:
<div id="fred" class="some-css-class" style="width:100vh" >
Hello
</div>
Docs
You just have to create a Parameter in your component. For example, this works fine. In a Tree component, TopDivClass parameter has been added an used.
In the markup of the component:
<div class="#TopDivClass">
In the code behind of the component:
[Parameter]
public string TopDivClass { get; set; }
In the markup using the component:
<Components.Tree TopDivClass="TreeView" />
The result in the HTML is
<div class="TreeView" ...
I've encountered a similar issue and Google led me here, so I share it for anyone who might hit this as well.
My project setup is .NET 7 and Teams App project template (Blazor Server).
The problem was similar to OP's - I wanted to apply CSS class to Web Component. In my case it was FluentTextField, so I couldn't modify its code.
Although doing this:
<FluentTextField
class="w-100"
Placeholder="Provide the URL"
Required="true"/>
wasn't producing any errors and in browser Dev Tools I could see the class added the element, i.e. <fluent-text-field class='w-100'>, the CSS defined in parent component wasn't applied.
Turns out, it's enough to change "Blazor syntax" to "JS syntax" and everything works fine:
<fluent-text-field
class="w-100"
Placeholder="Provide the URL"
Required="true"/>
Related
I have a pretty standard Razor pages project, and I've recently introduced Blazor components into the project. I've added the _Host.cshtml, App.razor, and the other requirements to get Blazor working. The Blazor components work fine when I'm at an endpoint that is exclusively Blazor components. However, I want to embed Blazor components within my current .cshtml pages using something like
#(await Html.RenderComponentAsync<EditorComponent>(RenderMode.Server, new { Id = Model.Id}))
withing my cshtml page. This syntax renders the component fine, but it doesn't run any of the Blazor lifecycle methods(OnAfterRenderAsync) or even something like a button calling back to a Task, in my EditorComponent component.
I've included the
<script src="~/_framework/blazor.server.js"></script>
at the end of element on my layout page. Am I missing something to get this working?
I think you might need to use the component tag helper instead.
Docs
<component type="typeof(EditorComponent)" render-mode="Server" param-Id=#Model.Id/>
As you've not provided a lot of code, I've built this code to try and reproduce your problem.
I can't: it works as I would expect it to. So unless either answer above solves your problem, you'll need to provide more code.
Start point Blazor Server template.
New razor page - _Test.cshtml
#page "/Test"
#namespace BlazorApp8.Pages
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#{
Layout = "_Layout";
}
<h1>Counter in a Page</h1>
<div class="m-2 p-2">
#(await Html.RenderComponentAsync<Counter>(RenderMode.Server, new { Starter = 6}))
</div>
Update Counter.razor to take a parameter.
[Parameter] public int Starter { get; set; } = 0;
protected override Task OnInitializedAsync()
{
currentCount = this.Starter;
return base.OnInitializedAsync();
}
Run and navigate to /Test.
I get the Counter page, OnInitialized sets the initial count to 6 and clicking on the button increments the counter.
Replace the blazor section in your _Layout.cshtml with =>
<head>
...
<base href="~/"/>
</head>
...
<script src="_framework/blazor.server.js" autostart="false" ></script>
<script>
Blazor.start({
configureSignalR: function(builder) {
builder.withUrl("_blazor");
}
});
</script>
...
Make sure to check your web console output. Blazor is likely throwing an error. This is pulled from every layout of every area in every app that I make. I've enjoyed a templated micro ui experience. Dotnet really makes it a breeze to proliferate your own designs via templates.
We're creating a dynamic page of components in Blazor. The intention is to have dynamic applets displayed on a page. The idea is that we have a list of strings which correspond to Component names. We read through the string list and for each one, instantiate a blazor component or render fragment. These are just simple components, no passed in parameters or the like. ie:
string[] componentsStrings = {"Component1", "Component2"};
Expected output:
<Component1 />
<Component2 />
We can't come up with a way to do this. It seems like a fairly standard thing to do, but perhaps not? Does anyone know if this is even possible?
You will have to programmatically create a component which adds your custom components on the page using RenderTreeBuilder.
Chris Sainty has a blog post on this which you can read here: https://chrissainty.com/building-components-via-rendertreebuilder/
Basically there is an override for BuildRenderTree in the ComponentBase class which can be used:
public class Menu : ComponentBase
{
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenElement(0, "nav");
builder.AddAttribute(1, "class", "menu");
}
}
Here is another tutorial.
Some tips from here:
Place base.BuildRenderTree(builder); at the start of the
BuildRenderTree method , not at the end.
Always start with the value 0 for the sequence parameter.
Looking for good practices about angular folder structure I stumble upon this piece of code:
content-layout.component.html:
<div [class]="theme">
<div class="mat-app-background">
<app-nav></app-nav>
<div class="container">
<router-outlet></router-outlet>
</div>
<app-footer></app-footer>
</div>
</div>
As far as I understand, the class tag is used to bind this component HTML with a CSS class.
But the square brackets caught my attention, is there any real difference between the [class] and class for css binding? I can't hit the correct search term/feature name to google it myself
the brackets [] indicate that the value is a property in your component, so instead of saying apply the class theme to the element, it will look for a property theme in your component and use whatever is stored in there.
class="theme" // apply class theme
// Component
public theme = 'theme';
// HTML
[class]="theme" // use what's stored in property "theme"
or
[class]="'theme'" // use string 'theme'
[] is a way to bind the data between ts and HTML, so in this case, the theme is a variable, on the other side container is a direct property
what you understood about class is right, where coming to [class], based on the value, class will be applied to that element. if the value is true or some value then that class will be applied to that element or else it will ignore that class. so basically you are using a specific class for some functionality and not using it for another
eg: <div [class.classOne]="true"></div> // now div element will have classOne class because result is true or some value.
references for better understanding about classes:
https://angular.io/api/common/NgClass,
Difference between [ngClass] vs [class] binding
I have created an Angular 6 library using 'ng generate library' command. This library is used in my base component after --prod build and then importing in app.module.ts of main application. The ...Component file in Library has #Input("leftPanel") leftPanel: ElementRef;
HTML Div element on base.component.html is like this: <div #leftPanel></div>
And the library element using its selector :
<lib-ng-mylibrary [leftPanel]="leftPanel"> </lib-ng-mylibrary>
Library component implements AfterViewInit. In the implementation method, this code execution fails: this.leftPanel.nativeElement.style.flexBasis = '50%';
it says, this.leftPanel.nativeElement is undefined. But i can see this.leftPanel point to the div. Wonder why it does not allow this.leftPanel.nativeElement` even tho #Input leftPanel is of type 'ElementRef'?
Thanks in Advance!
Harshad
Instead of sending the parent ElementRef my feeling is that your component should have and #Output and trigger an event handled by the parent, to change the native panel width.
Doing like you reduce the coupling between the object and make them more reusable.
See docs here: https://angular.io/guide/component-interaction
Still want to use ElementRef as parameter
If you still want to send the leftPanel as a parameter, you will need an #Input() variable in your main component as well, so it can resolve <div #leftPanel> to a local variable and that variable be used in [leftPanel]="leftPanel"
cheers
This question already has an answer here:
Custom HTML tag attributes are not rendered by JSF
(1 answer)
Closed 2 years ago.
I am using Primefaces 3 in JSF 2 to make a search box. I need to add a non-standard attribute (x-webkit-speech) to the control so you would have something like this...
<p:autoComplete x-webkit-speech="x-webkit-speech" ... />
Since this attribute isn't part of the autoComplete control JSF gives me a 500 error. But when I remove it, the page renders fine. In general, how do you specify pass through attributes on a JSF tag so they are ignored?
JSF by design ignores all custom attributes when rendering HTML.
If you're already on JSF 2.2+, simply specify it as passthrough attribute:
<html ... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
...
<p:autoComplete a:x-webkit-speech="x-webkit-speech" ... />
If you're not on JSF 2.2 yet, then you need a custom renderer. This is in case of PrimeFaces <p:autoComplete> (and all other components) fortunately relatively simple. It's sufficient to override just the renderPassThruAttributes() method wherein you add the new attribute which you'd like to render to the attrs argument and finally delegate to the super method.
E.g.
package com.example;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import org.primefaces.component.autocomplete.AutoCompleteRenderer;
public class MyAutoCompleteRenderer extends AutoCompleteRenderer {
#Override
protected void renderPassThruAttributes(FacesContext facesContext, UIComponent component, String[] attrs) throws IOException {
String[] newAttrs = new String[attrs.length + 1];
System.arraycopy(attrs, 0, newAttrs, 0, attrs.length);
newAttrs[attrs.length] = "x-webkit-speech";
super.renderPassThruAttributes(facesContext, component, newAttrs);
}
}
To get it to run, register it as follows in your webapp's faces-config.xml:
<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.AutoCompleteRenderer</renderer-type>
<renderer-class>com.example.MyAutoCompleteRenderer</renderer-class>
</renderer>
</render-kit>
(you can find out the component family and renderer type by looking at the source code of AutoComplete class, they're specified as COMPONENT_FAMILY and RENDERER_TYPE constants in there)
No, the #FacesRenderer annotation simply won't work when the purpose is to override custom renderers which are by itselves already registered in a faces-config.xml.
The most Tags can be extended, using the Attribute-Tag from JSF-Ext.
<html xmlns:h="http://java.sun.com/jsf/html" xmlns:e="http://java.sun.com/jsf/ext">
<!-- ... -->
<h:inputText id="name" value="#{bean.name}">
<e:attribute name="placeholder" value="My Name"/>
</h:inputText>
<!-- ... -->
</html>
You can configure it via maven:
<dependency>
<groupId>com.intersult</groupId>
<artifactId>jsf-ext</artifactId>
<version>2.2.0.1</version>
</dependency>
JSF-Ext is a library from http://www.intersult.com/wiki/page/JSF%20Ext
I am not sure if this is possible at all. I would add those attributes on the client side using javascript or jQuery.
You can put el expressions into your javascript code if you want to integrate server-side stuff.