C# property name change effects ID in HTML - javascript

c# code:
public class Person{
public string Name { get; set; }
public age int { get; set; }
}
cshtml code which generates an id of #Person_Name
#Html.DropDownListFor(m => m.Person.Name)
javascript code:
$('#Person_Name').on("change", function () {
//Do something
}
If I change the Person class property name from Name to FullName. The next step is to modify the cshtml code to read as:
#Html.DropDownListFor(m => m.Person.FullName)
I understand you can manually go in and change the Jquery code, but if this change is made and the person making the change is unaware of the jquery, it is going to cause an error. Is there a way to prevent this from happening through some form of notification or logging? Rather than just remembering that the jquery needs to be changed.

You do have the option to use:
#Html.IdFor(x => x.Person.FullName)
Or
#Html.NameFor(x => x.Person.FullName)
That does rely on having small bits of script in pages, but for what id do this is mostly calling functions in .js resources which from my point of view I find better for reuse anyway.
You may still not get alerted to all issues unless you choose to compile your MVC views, you'll probably get a warning if you have the view open. How you set up your project to compile your MVC views will depend on the type of project but a quick Google should help with that one.

Related

Is there a way to use a reference to an existing java class from javascript in Vaadin?

i currently have the problem, that i want to use a reference of an existing java class in javascript to be able to execute methods from Javascript of the Java Class to use Shepherd (Javascript Tool for guiding users through the web app). Im using Vaadin for Web deployment with java but Shepherd only works through Javascript.
I dont want to execute the JS from the Class with the methods, moreover i want to execute it from an other class, so it looks like this:
User clicks on a Button
Button button = new Button(); button.addClickListener (c -> tourPageController.executeShepherd(UI.getCurrent().getInternals().getTitle());
Java Code to find active Page
public static void executeShepherd(String appTitle) {switch(appTitle) {case "example": UI.getCurrent().getPage().executeJs("window.startTour($0)", <here i want to reference the existing class with the methods);
execute the Shepherd Tour four the explicit page, the user is on (For that, i need to hand over
a reference of the class holding the methods to execute via javascript), its looks something like this in the header:
window.startTour = () => { ... }
Javascript is getting the parameter (the class)
From Javascript im going to use Shepherd, but there are references to Java Methods (these Methods are for the Vaadin Components, to open and close the respectively tabs i want to use in the tour). I use it like this:
beforeShowPromise: function () {
return new Promise(function(resolve) {
classParameter.$server.<method()>;
resolve();
});
},
How can i do this?
What you can do is to set id to the component in Java
component.setId("component-x");
This will mean that the DOM element will be have the id attribute set.
So if you have some bookkeeping of the components in your Java code, you can pass the id as a parameter in that #ClientCallable call, and then search for the component matching that id in your Java code.
If this is about only one view specific component, you do not need anything else than storing reference to the component in a class field (not even the id). But if you indeed have more than one Accordion in your view, the idea is like this.
public class MyView extends Div {
List<Accordion> accordions;
public MyView() {
Accordion accordion = new Accordion();
accordion.setId("accordion-1");
accordions.add(accordion);
...
}
#ClientCallable
public openAccordion(String id, int index) {
accordions.stream().filter(acc ->
acc.getId().equals(id)).findFirst().ifPresent(acc -> acc.open(null));
accordion.open(index);
}
}
For context, see: How can I change Vaadin Components in Java through Javascript

Blazor - Call JavaScript from C# class

Here is what I want to achieve:
I have a (normal) class in a Blazor WASM project. I want to invoke a JavaScript function from my class.
If I want to do this from a Razor component it is working fine, I inject IJSruntime and invokevoidasync to my JavaScript.
But it goes wrong when I try to do it from a class.
First I tried to inject it like this:
[Inject]
IJSRuntime JSRuntime { get; set; }
But ended up with error message: Value cannot be null. (Parameter 'jsRuntime')
I learned from this post that I have to "Inject it in the traditonal way", so I did this:
public class InvokeJavaScript
{
private readonly IJSRuntime jSRuntime;
public InvokeJavaScript(IJSRuntime jSRuntime)
{
this.jSRuntime = jSRuntime;
}
public async void InvokeMyJs()
{
await jSRuntime.InvokeVoidAsync("giveMeAMessage");
}
}
But from there on I am stuck, I know that this must be some key .NET knowledge but I am missing a piece here.. I want to call the "InvokeMyJs" methode like:
InvokeJavaScript ij = new InvokeJavaScript();
ij.InvokeMyJs();
But know I am facing an error: There is no argument given that corresponds to the required formal parameter 'jSRuntime' of 'InvokeJavaScript.InvokeJavaScript(IJSRuntime)'
That I get the error makes sense to me but I dont know how to fix it, what parameter must I send to InvokeJavaScript(IJSRuntime jSRuntime) and how do I do it correctly? Can anyone give an example?
When you use DI you have to follow it through.
In general that means avoiding new, as in:
InvokeJavaScript ij = new InvokeJavaScript(); // no parameter
register the InvokeJavaScript as a Service in Startup.
inject it where you need it.
Program.cs
builder.Services.AddTransient<InvokeJavaScript>();
SomeComponent.razor
#inject InvokeJavaScript ij

What sould I add for the last line of my code '(this,R.layout.device_name)'? [duplicate]

What is the meaning of R.layout.activity_main ?
I understand that "." operator is used to define variables of a particular object but in this case its been used twice so I can't make anything out of it. Also what exactly is "R" and "layout"?
I mean obviously they are classes (right?) but what is their function ? Basically explain R.layout.activity_main !
Please comment if question too vague or too broad.
R.java is a class (with inner classes, like layout or string) generated during the build process with references to your app's resources. Every resource you create (or which is provided by Android) is referenced by an integer in R, called a resource id.
R.layout.* references any layout resource you have created, usually in /res/layout. So if you created an activity layout called activity_main.xml, you can then use the reference in R.layout.activity_main to access it. Many built-in functionality readily accepts such a resource id, for example setContentView(int layoutResid) which you use during the creation of your activity and where you probably encountered this particular example.
If you create a string resource (in strings.xml) like this:
<string name="app_name">Application name</string>
it will get a new reference in R.string.app_name. You can then use this everywhere where a string resource is accepted, for example the android:label for your application in AndroidManifest.xml, or on a TextView; either in the xml:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"
/>
or in code: textview.setText(R.string.app_name).
You can access resources programmatically using the Resources class, to which you can get a reference by calling getResources on any context (like your activity). So for example you can get your app name described above in your activity by calling this.getResources().getString(R.string.app_name).
You can also supply different resources for different device properties/settings (like screen size or language), which you can access using the same references in R. The easiest example here, imho, is strings: if you add a new values folder in /res with a language specifier (so /res/values-nl for Dutch) and you add strings with the same identifier but a different translation and the resource management system cleverly figures out which one to provide for you based on your user's device.
I hope this helps a bit. For more information on resources see the documentation.
R is an auto-generated class, and describe the resources of your project. It contains static inner classes. layout is one of them. R.layout refers to the inner class called layout. activity_main is a public static final member of the class layout
In Android R is an Java-class that is auto-generated from your resources by the build process.
The R.layout member is a auto-generated class that contains all IDs for layouts.
R.layout.activity_main is a static final int member that represents the ID of the layout-file in layout/activity_main.xml.
Okay, so R is a generated class. If you're lucky enough you'll never see it nor have to touch it, otherwise you did something very wrong.
When you make a layout, or any change to a layout, Android Studio generates quite a couple files for you. This includes a R.java file. Here's a piece of an R.java class:
public final class R {
public static final class anim {
public static final int abc_fade_in = 0x7f050000;
public static final int abc_fade_out = 0x7f050001;
public static final int abc_grow_fade_in_from_bottom = 0x7f050002;
public static final int abc_popup_enter = 0x7f050003;
public static final int abc_popup_exit = 0x7f050004;
public static final int abc_shrink_fade_out_from_bottom = 0x7f050005;
public static final int abc_slide_in_bottom = 0x7f050006;
public static final int abc_slide_in_top = 0x7f050007;
public static final int abc_slide_out_bottom = 0x7f050008;
public static final int abc_slide_out_top = 0x7f050009;
}
public static final class attr {
public static final int actionBarDivider = 0x7f010062;
public static final int actionBarItemBackground = 0x7f010063;
public static final int actionBarPopupTheme = 0x7f01005c;
public static final int actionBarSize = 0x7f010061;
public static final int actionBarSplitStyle = 0x7f01005e;
public static final int actionBarStyle = 0x7f01005d;
public static final int actionBarTabBarStyle = 0x7f010058;
public static final int actionBarTabStyle = 0x7f010057;
public static final int actionBarTabTextStyle = 0x7f010059;
As you can see, in this case if I'd type
R.anim.abc_fade_in
I'd be selecting the value 0x7f050000;.
Every layout file is mapped out in this R file, and gets an ID by which android recognizes it. The layouts are located in R.Layout. So, R.layout.activity_main gets you the value of variable activity_main of the class layout of the class R.
And again, don't try finding or changing your generated R file. Things can go very wrong if you do that.
From https://stackoverflow.com/a/4953282/1393766
R is a class containing the definitions for all resources of a particular application package. It is in the namespace of the application package.
If you want to inflate a layout inside your activity class,you can use R.layout.activity_main where layout specifies that your resource is a layout and it's name is activity_main.
If you want to use a drawable image in a layout inside your activity class,you can use R.drawable.image_name where drawable specifies that your resource is a drawable image.
Also,R.java class is an autogenerated class which is not supposed to alter manually.

Where should my Javascript go for View Components?

I'm getting used to view components in MVC 6, and I asked a similar question a few years ago about partial views. If I build a view component encapsulating a common use-case that requires its own Javascript, where do I put that Javascript? I know that it is dangerous at best to have Javascript in partial views, but it would be a lot simpler to include it in the view component, rather than in the containing view or a separate file that has to be referenced by the containing view.
For example, say I have a view component that has two drop-downs. The selection in the first drop-down determines what items appear in the second drop-down. This is easily handled in Javascript, of course, but where do I put it?
From my experience with ASP.NET 5 View Components, I would say that the best thing to do with them is to keep them isolated and in one place, so they will be easily to manage in long-term projects.
In one of my ASP.NET projects, I've developed View Components structure like this one:
View, Backend code and Model are all in one place, so when you move around the folder, you are sure that you move whole component. Moreover, when you are modyfying them, you have quick access to all of their parts.
It will be convinient to put JavaScript which is highly coupled with a component also in such structure. You can do this by simply creating the file under the component's folder, and then writing a GULP TASK that will copy JS file to wwwroot. From that point, you will be able to link that JavaScript code on component's .cshtml using standard syntax:
<script src="~/Components/yourcomponent.js"></script>
To obtain such a structure in my project, I've extended Razor, to be able to search for my component's CSHTML's in proper place. To do this, I've added this code in Startup.cs:
public partial class Startup
{
public void ConfigureServices(IServiceCollection services)
{
//non relevant code skipped
services.AddMvc().AddRazorOptions(ConfigureRazor);
}
public void ConfigureRazor(RazorViewEngineOptions razor)
{
razor.ViewLocationExpanders.Add(new ViewLocationExpander());
}
}
and the ViewLocationExpander class is:
public class ViewLocationExpander : IViewLocationExpander
{
protected static IEnumerable<string> ExtendedLocations = new[]
{
"/{0}.cshtml"
};
public void PopulateValues(ViewLocationExpanderContext context)
{
//nothing here
}
public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
{
//extend current view locations
return viewLocations.Concat(ExtendedLocations);
}
}
Then, you invoke component like this (from any .cshtml view):
#await Component.InvokeAsync("NavigationComponent",new NavigationComponentModel())

Setting Breeze Navigation Property in Knockout subscription

I am building a SPA (Single Page Application) using Breezejs and Knockoutjs.
I am running into an issue when trying to set a navigation property inside a knockout subscription. On the final line of the ko.subscription the console.log function shows me the entity, however, the WebPresences navigation property is null.
Not sure if the fact its in a ko.subscription really matters but I've been able to set the navigation prop just in a js function I call right before save, so I think it has some significance.
So here is my Entity Model
public partial class Entity
{
public int Id { get; set; }
public string Name { get; set; }
public Nullable<int> WebId { get; set; }
public virtual WebPresence WebPresence { get; set; }
}
And here is my ko.subscription and relevant variables:
var vm = {
newEntity: ko.observable(datacontext.createBreezeEntity('Entity')),
newWebPresence: ko.observable(datacontext.newBreezeEntity('WebPresence')),
}
vm.newEntity().WebPresence.subscribe(
function (data) {
var self = this;
if (data === null)
self.target(vm.newWebPresence());
console.log(vm.newEntity());
}
);
And last but not least my datacontext
createBreezeEntity: function (entityName) {
return manager.createEntity(entityName);
},
newBreezeEntity: function (entityName) {
return manager.metadataStore.getEntityType(entityName).createEntity();
}
I do not understand what you're striving to accomplish.
One thing I'm pretty confident about ... is that your the datacontext.newBreezeEntity creates an object that is just hanging in thin air and isn't part of any navigation property.
Let's look at your datacontext.newBreezeEntity method:
return manager.metadataStore.getEntityType(entityName).createEntity();
This indeed does create a new entity of the type named entityName. But this is a 'proto-entity'. It does not belong to an EntityManager ... certainly not to the manager instance. It isn't related to any particular other entity (e.g., your mysteriously-named Entity entity). It's just a detached entity.
I'm betting you thought that it would belong to manager because you started the expression there. Well it doesn't. You lost the connection with manager the moment you asked for its metadataStore.
But there is so much else that makes no sense to me at all. I can't tell why you're subscribing to vm.newBreezeEntity nor why it's called "newBreezeEntity" nor what it's relationship is supposed to be to vm.newEntity nor what you think this is within the subscription function.
Perhaps you should step back and describe what you WANT this code to do.

Categories

Resources