Giter Site home page Giter Site logo

hassanhabib / prettyblazor Goto Github PK

View Code? Open in Web Editor NEW
99.0 13.0 19.0 68 KB

PrettyBlazor is a Blazor .NET library that enables Blazor developers to use control structures in their Blazor applications through markup without having to use obtrusive C# code to iterate or select particular fragments.

C# 98.56% HTML 1.44%
blazor blazor-webassembly blazor-server blazor-client blazor-component

prettyblazor's Introduction

.NET Nuget The Standard - COMPLIANT The Standard Community

PrettyBlazor

PrettyBlazor is a Blazor .NET library that enables Blazor developers to use control structures in their Blazor applications through markup without having to use obtrusive C# code to iterate or select particular fragments.

Introduction

There are two concepts here that makes PrettyBlazor important for writing clean, readable and unobtrusive Blazor applications.

Control Structures

In computer sciences there are three types that makes the types of control for any given program. These types are sequence, selection and iteration.

Sequential Structures

Sequence already exists in any markup language, as it simply means you can sequentially build markup blocks one after another and they shall render accordingly as follows:

<TextBoxComponent />
<ButtonComponent Label="Submit" />

Selection Structures

Selection structures are responsible for executing particular blocks of code only when a given evaluation or a condition is positive. the most common example for selection structures are the if-else statements, but it extends to other forms such as switch case. Most of Blazor developers today will handle the selection flow by simply directly adding obstrusive C# code into their .razor files as follows:

@if(condition)
{
    <SomeComponent />
}
else 
{
    <SomeOtherComponent />
}

The problem with the above code snippet is that it violates multiple principles. For instance, it's very cognitive-resources consuming to write a particular file of code with two different languages. You require the engineers reading the code to mentally switch back and forth between C# and Markup to understand what your code is actually trying to accomplish. This might not be a big deal when writing a simple demo "Hello, World!" program. but for large scale enterprise applications this could become quite consuming and may cripple the ability for some engineers to easily detect any issues in your code. The issue with obtrusiveness in C# code with Markup in Blazor is that the text editor and the parser are in continuous intrepretation of what your code is actually to accomplish, which can have some performance issues as well.

With Pretty Blazor, the equation becomes much simpler, because the entire file will be written simply by one and only one language which is markup as follows:

<Condition Evaluation="condition">
    <Match>
        <SomeComponent />
    </Match>
    <NotMatch>
        <SomeOtherComponent />
    </NotMatch>
</Condition>

In the code snippet above, you can see the selection structure completely implemented with just markup. the only C# code in this place is just the references to a boolean calculated value which belongs in the C# file for this application. This approach of implementing selection control structure, is more befitting for the overall flow of a markup language in general, it expresses the structure much more fluently without any interruptions using a different language or a technology. Every scripting, markup or programming language out there has the ability to express the type of control in their own way, for instance, CSS expresses selection control as follows:

#button {
    color: red;
}

This is basically CSS way of saying, if the element id is named #button then go a head and assign color red to it. The same thing goes for all other scripting and programming languages, very few on the markup side, therefore PrettyBlazor brings this level of control to the markup world with Blazor components.

Iteration Structures

Iteration is one of the most powerful features in every scripting or programming language. Just like selection and sequence it is very heavily used almost in every single application on the planet. Iteration allows engineers to pass in a list of items and have some form or redundant routines to execute on each one of these items. Today in Blazor, you'll see a lot of applications being written as follows:

@foreach(Student student in students)
{
    <StudentComponent Value=student />
}

And again, the problem with this structure here is the obtrusive nature of the implementation, which requires multiple technologies and programming/markup language to collide to achieve a certain implementation. Some folks decided to take the route of building the entire component in C# then just return a rendered component or a fragment on the markup, and that's one way and rather hard way to solve the problem. But an easier approach would be to implement the same concept with a fluent markup expression as follows:

<Iterations Items="Students">
  <StudentComponent Value="@context" />
</Iterations>

In the code snippet above, you can see how simpler, easier and prettier it can be to express an iteration in Blazor without having to write any specific C# code in your markup. And just like we said in the selection section, the iteration control structure can be seen in every scripting, styling and programming language out there, for instance, in CSS iterations can be implemented as follows:

button {
    color: red;    
}

In the example above, every single element of type button will have the color red. This is just another form of expressing iterations.

Unobtrusive C#

Over a decade ago, web engineers introduced the concept of unobtrusive JavaScript. which was mainly around the idea that a web application should have it's CSS, HTML and JavaScript code all separated in their own files without one of them having to be using in the other's files. This earlier concept has changed a lot since then, web applications have evolved dramatically and it seemed that this concept has become less of a priority in some populator frameworks. PrettyBlazor attempts to bring this idea back, as it makes the code consumption of engineers' cognitive resources much lesser and more pleasant to read through and detect any issues in any if any. The idea of Unobtrusive C# is to mainly ensure that C# code stays within .cs files and it shall be it's only responsiblity to describe the actions of UI components or the events that follow within. And that's why PrettyBlazor was made, to litterally make developing Blazor applications prettier, easier to understand and faster to implement.

Here's a more combined example of PrettyBlazor:

<Iterations Items="Numbers">
  <Condition Evaluation="@(context%2 == 0)">
    <Match>
      <p>It's true!</p>
    </Match>
    <NotMatch>
      <p>It's false!</p>
    </NotMatch>
  </Condition>
</Iterations>

The equivelant of writing the same statement in Blazor today would be:

@foreach (int number in Numbers)
{
    if (number % 2 == 0)
    {
        <p>It's true!</p>
    }
    else
    {
        <p>It's false!</p>
    }
}

C# mixed with html - which can become quite problematic from a readability, maintenance and performance perspectives when used in a large scale application - no matter how simpler you try to make the system components to be.

Installation

Command Line (execeute this in the directory your project file is located)

dotnet add package PrettyBlazor

In your Component (or _Imports.cs)

@using PrettyBlazor

Challenges and Dreams

PrettyBlazor is only a good start to a full unobtrusive C# routines in a Blazor application, the true issue here still stands with some of the C# code even if it's just a reference invading the space of the markup instead of gracefully handling the non-blazor or js availability with a graceful failure for the HTML body to load without having to add any additional logic. The dream state is to allow C# to find and attach events or property values to Blazor components from the back-end without having to have any references whatsoever on the front-end.

here's a video introduction to this library:

IMAGE ALT TEXT HERE

If you have any suggestions, comments or questions, please feel free to contact me on:
Twitter: @hassanrezkhabib
LinkedIn: hassanrezkhabib
E-Mail: [email protected]

prettyblazor's People

Contributors

adbir avatar baltermia avatar hassanhabib avatar imjane5 avatar shrihumrudha avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

prettyblazor's Issues

Allow other enumerable types in the Iteration component

I've noticed that the Iteration component seems to be hardcoded to only take a List.

If an ICollection or IEnumerable is provided, for example, the error is also rather confusing.

Would it be possible to allow IEnumerable on the Items parameter? Or is there a specific reason why it has to be List?

Consider adding an Index to your Iterator

We started down the path of doing things like you are doing, but came up with a slightly different approach for the Iterator and Iterations... Essentially, we tried to keep as much of the razor tags as close to C# as possible. This implementation breaks one thing I like better about yours... and that is you have direct access to the object in the loop. With the below method,, one must understand you have an Item as well as an Index.

public class ComponentContext<T> where T : ComponentBase
{
    public ComponentContext(T @component) => Component = @component;
    public T Component { get; set; }
}

public class ForEach<T> : ComponentBase
{
    [Parameter]
    public IEnumerable<T> Items { get; set; }
    [Parameter]
    public RenderFragment<ForEachContext<T>> ChildContent { get; set; }

    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        var index = 0;
        foreach (var item in Items)
            builder?.AddContent(0, ChildContent(new ForEachContext<T>(this, item, index++)));
    }
}

public class ForEachContext<T> : ComponentContext<ForEach<T>>
{
    public ForEachContext(ForEach<T> component, T item, int index) : base(component)
    {
        Item = item;
        Index = index;
    }
    public T Item { get; }
    public int Index { get; }
}

Merge the 2 readme files

I realized that there are two different readme-files in this project. After forking the repository and cloning it onto my windows machine I got the following git warning:

warning: the following paths have collided (e.g. case-sensitive paths
on a case-insensitive filesystem) and only one from the same
colliding group is in the working tree:

  'README.md'
  'readme.md'

The two files are not identical and have both been updated separately a few times. They should be merged into one file.

Visual Studio 2022 does not see Condition as an if statement

During development, I check for null reference pointer exceptions, i.e. from my Fluxor states, using the PrettyBlazor package.
This is not picked up by Visual Studio.
This does not register:

<Condition Evaluation="UserState != null">
    <Match>
        @UserState.Value.User.FullName
    </Match>
</Condition>

This does:

@if(UserState != null)
{
    @UserState.Value.User.FullName
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.