Currently, I'm assessing viability of Blazor for our projects and I want to better understand JavaScript's role in a Blazor project.
Microsoft documentation states the following:
Only mutate the Document Object Model (DOM) with JavaScript (JS) when
the object doesn't interact with Blazor.
If I understand this correctly, JS should only be used in Blazor projects as an absolute last resort.
We often use nicely and professionally designed templates that come with a ton of nice features that are all built with JS. Some examples include date picker, carousel, toast notifications, etc. This approach not only saves us a ton of time but also most of these templates come with everything we need, eliminating the need to piece-meal components that may or may not match in design or behavior which is a very important UX factor for us.
If I understand Microsoft's statement correctly, we should no longer use these templates and try to find Blazor equivalents of such features. Is this a correct assumption on my part? If so, this would be a major disadvantage for us to use Blazor.
P.S. Not sure if it matters but our choice would be the Web Assembly option with Blazor.
Is this a correct assumption on my part?
No, it is a wrong assumption on your part...
You may use many of the templates in your possession, but you should know how to do that.
The main thing to understand is that if an element's state has been mutated by JS code, Blazor may ignore it; that is from the vantage point of Blazor nothing has changed. Let me try to give you an example that may clarify what I mean:
Suppose you have a page with a form to gether the name and age of a user... For this, I'll use a form element within which I embed two input type text elements. Both text elements are bound to, say properties defined in a class named User. Ordinaraly, we apply two-way data binding; that is the flow of data is from a variable to the element and from the element to the variable:
Public string Name {get; set;}
Now suppose you run your Blazor form page, you type "Steve Sanderson" in the Name textbox, and then navigate to the Age textbox and enter a value. Now before you click on the submit button to submit the form data, you click on another button that executes JS code that perfom a search for an element with id="name", and when found assignes the value "Blazor" to its value property. Now you can see the Name textbox with the value "Blazor" instead of "Steve Sanderson". You can now click on the "submit" button. Usually you would expect the Name property to contain the value "Blazor" as that was the last value (set by JS). But Blazor ignore your entics, and the Name property actually contains the value "Steve Sanderson". This is because Blazor handle the binding, it creates a virtual Dom, it a has a complicated process of rendering, etc. In short, it ignores the mutation made to the elements' state from JS. Or in other words, the changes made by the JS code do not participate in the binding process made by Blazor.
When I started learning Blazor, I created a carousel, 100% Blazor. I did it in order to learn Blazor. I inspected the code of the Bootstrap carousel, and imitated the way it works and looks. Very often you can take a widget created by JS, and implement it in Blazor. The market, however, is full with implementatios in Blazor.
Except for education purposes, I'll never implement a widget created in JS, when I can use it as is. Why create a carousel with Blazor just for the display of images, a widget that has no interaction with Blazor. In that case, it would be wiser and more appropriate to use it as a JS widget. Blazor doesn't care. But if you need a sophisticated carousel that trigger events, sent data, etc., you may need to implement it with Blazor, but more often to use JS Interop with your JS widget, as related below...
Here's a link to a sample that explain how to embed a Leaflet map on a Blazor SPA, using JSInterop. This is how usually you should work.
As usual, it depends on what you know, and what specifically you're trying to do.
If Javascript is changing objects that are defined in Blazor markup, especially if it ever moves them around the DOM tree, deletes or duplicates them, you have an obvious problem-- Blazor will have an incorrect model of the page, and results could be inconsistent.
However, it may be that all the JS does is just eye-candy: animating scrolls, flashing icons, rotating through a list of images, etc. It's perfectly possible that none of that will conflict with anything you're doing in Blazor.
If you have simple entry points (like a 'toast' that's just a Javascript function with a string variable input), then JS Interop will be trivial.
If you have something more complex, like a large table of data that you want to sort and page, then unless you know EXACTLY how things work, you get unexpected results.
Related
I'm new to Ractive.js and wondering if there's a lifecycle event I can use to know whenever Ractive is done making DOM updates in response to data changes?
My use-case is that I have a grid of boxes (simple divs) rendering some text from the data model. Whenever my data model updates, Ractive is properly updating the DOM for me. But when it's finished with that, I want to dynamically adjust the font size within each box to make sure the text fits.
This is just the first thing that crossed my mind for sizing my text to fit and it might not be the right solution... but I'm surprised I haven't found such a lifecycle event?
Here's the doc I'm looking at: http://docs.ractivejs.org/latest/lifecycle-events. My application is using magic mode to handle updates.
Unless someone more knowledgeable basically corrects the documentation, it looks like there's no lifecycle event to listen to.
However, I've discovered that Ractive's concept of Decorators give me the functionality I was looking for. By passing a Decorator to my Ractive instance, I get passed the DOM nodes created by RactiveJS and I'm able to do whatever work I need to do (in my case, computing whether the text in the node fits in its container and scaling it down in Javascript).
In my application there is two types of registration. Business type and individual type. Business type has some extra fields to be filled. I dont want to use two forms.
What I want is When the user clicks on Individual reg.. , some text boxes will be hidden and when Business type user clicks on the radio button every field should appear. I dont want to use jquery. How can we achieve this in asp.net mvc4
You can do something like below without Javascript.
Assuming your controls are inside div's, and two css classes (div-visible, div-hidden) are defined accordingly.
<div class="#(Model.IsBusinessType?"div-visible":"div-hidden")">
//Business controls
</div>
<div class="#(Model.IsBusinessType?"div-hidden":"div-visible")">
//Individual controls
</div>
I think there are at least three approaches you can take depending on a few factors...
1) Basic Javascript (if you're not going to do this kind of thing more than once/often in your project)
document.getElementById("yourID").style.display='none'...'block'... and so on
2) jQuery - if you need this kind of thing a little more often, plus all the other great things that jQuery can do
look up jquery hide() and show() functions - pretty easy to do ('#yourID').hide()...show()
3) Knockout.js - a more comprehensive way to bind data client side and can easily do what you describe, but does so much more than this too - more of a learning curve, but great tool if you need significant client-side functionality like this - probably overkill if you don't need much more than you describe.
I have to create a Dynamic menu in ASP.NET. I want to use dynamic LinkButtons (or can be a Menu Control), but should be appended with sequence numbers. Eg: 1,2,3a 3b etc..and these sequcenes could be dynamic. Any idea. I used a repeater with a label and LinkButton in it, but having problems with view state. Any idea how to append sequence to menu??
Essentially, you have two paradigms with web applications, at least from this conversation's standpoint.
Stream out the HTML, creating it as you stream
Create containers that can bind to data and shape the data
Your concept seems to be "only #1 is dynamic", but that is not true. Any time you can change the data and get a different output, you are dealing with something dynamic. My personal feeling is shape the menu data prior to binding. This cannot always be done, but more oft than not, it can. The second method would be to attach to an event like a item binding or row binding event. Controlling the HTML stream and writing out individual items is generally my last resort.
Now to the viewstate issue. Viewstate is a bastard when you start adding things to an item after binding and semi-problematic when you are playing the dynamic game from #1 above. The problem is things added after the initial definition cannot easily be set up with automagic bits. You end up having to rebind each time. This is why shaping data and then binding is superior. Even in cases where you have to rebuild, you can cache the shaped data and quickly rebind. It takes more "up front" work, but is less problematic.
The actual container you are binding with is inconsequential. Unless you can't use the menu control for some reason (other than having to dynamically add, which can be solved by playing with the bound data), I would head this direction. Actually, I would head this direction and use the CSS friendly adapters so you can alter the look and feel more easily. :-)
In the examples for RobotLegs, it appears that mediators are used on every button/textArea, rather than on the custom component that contains these children. This would be very time consuming would it not?
From Joel Hooks InsideRia Example
Dependency injection works better with
unambiguous classes. What this means
is that by extending TextArea into our
new MessageView class, we are creating
a specific view component for the
dependency injection to act upon. This
is important if our application were
to have several TextAreas that served
different purposes. By dividing up our
classes in this way, we are clearly
defining the intent of the class and
allowing for the dependency injection
tools to do their jobs effectively.
No, don't mediate every child component. Your components should be organized into groups that perform related actions. In the examples the components are extremely simple and do not reflect what a real application would look like.
One rule of thumbs I use is thinking if that component needs any communication with the rest of the application, or if its only a part of a whole. Keep in mind that mediator are only intended to serve as a bridge between the view and the app.
For example, if I've a view with a form (asume a login form) I don't mediate all the child components (the textfields, the buttons, etc.) because it would be pointless and would have a proliferation of classes and objects on runtime. When I do the form I think, what does the view by its own? and what the other parts of the app should do with it?
When the user fills the form and clicks a button, the view dispatches an event (LoginRequestEvent, for this case), and then the mediator should redispatch that event, making the mediator very lean.
But with practice of the framework, you'll come up with this feel of what you shold mediate. For instance, in one app I mediate every item renderer of a list, and on other I mediate a view stack with two or three navigation contents.
Hope it helps
When I try to access the hidden TABs of my tab navigator control in action script, it returns a null error. But it works OK if I just activate the control in the user interface once. Obviously the control is not created until I use it. How do I make all the tabs automatically created by default ?
<mx:TabNavigator creationPolicy="all"/>
That should do it. Deferred instanciation is a feature, but sometimes it is a hassle.
The Flex framework is optimizing creation be default (creationPolicy="auto") so if you have a configuration dialog with a lot of tabs, for example, and the most useful tab is the first one, your application does not spend time and memory initializing the tabs that the user never sees.
This makes a lot of difference when dialogs like this never release, and is a good default to go with.
One thing to look at is using a private variable in your dialog/form instead of pushing the data to the control on the hidden page. This style treats the whole form as if it were a component, which it sort of is. To repeat: the MXML form/dialog/canvas is a class, and it can have data and methods in addition to containing other components.
Cheers
On a side note, I've run into the deferred-loading policy in a multi-state application, and circumvented it by forcing all elements to be included and invisible in the initial state. Something to consider, but only as a hack.