saving part of JSON in a function invoked in the html file - html

I'm developing in Angular.
I'm trying to save part of a JSON in a variable inside a function called in an HTML file:
<select id="postazione" onchange="postazioneSelezionata()">
<option value="" selected disabled >Scegli una postazione</option>
<option *ngFor="let postazione of postazioniNome" value="{{postazione}}">{{postazione}}</option>
</select>
(the onchange="postazioneSelezionata()").
it seems works, because if I try to print the value I'm interested in inside the console.log, it is shown correctly.
postazioneSelezionata(){
this.postazione = document.getElementById("postazione").value;
console.log(this.postazione);
}
inside the function i'm also trying to show this in the terminal:
console.log(this.fileJson.ricette[this.postazione]);
Here comes the problem...
If i try to show the part of the JSON this.fileJson inside the console.log(), it return me an error:
ERROR TypeError: Cannot read property 'ricette' of undefined
at HTMLSelectElement.postazioneSelezionata [as __zone_symbol__ON_PROPERTYchange] .
i've tried to show it in another function (not called from an html onchange event)
this.postazione = "GRIGLIA";
console.log(this.fileJson.ricette[this.postazione])
and it works... this code (called in another function) show me the portion of the fileJson JSON i'm trying to obtain

Possibly this post will be of help.
Additionally, even though you say your onchange works, the standard syntax for such events with Angular, as m.akbari mentioned in his comment, is (change):
<select id="postazione" (change)="postazioneSelezionata()">
...
</select>
And from there, unless you're not particularly bothered about the value of the change and just care to know that something was changed, you would probably pass the value in that changed...
<select id="postazione" onchange="postazioneSelezionata($event.target.value)">
...
</select>
Similar changes, syntax-wise, in your options for entering your value:
<option *ngFor="let postazione of postazioniNome" [value]="postazione">{{postazione}}</option>
Input/output binding, two-way binding, event binding... all are fairly integral to Angular, it's worth getting them figured out.
Again, see the post linked at the top for a more rounded answer and examples to using selects with Angular.

Related

Idiomatic way of passing both event and local vue variable to bound function

I was trying to figure out how to access both a v-for member and the original event data to a bound function on an event in vue.js, but couldn't for the life of me find it in the documentation.
What I want:
<div class="card pickup" v-for="pickup in pickups">
<select v-on:change="locationChanged">
with locationChanged calling the following method in my vue object:
vuePickup = new Vue({
el: '#pickups',
data: {
pickups: pickups,
},
methods: {
locationChanged: (event, pickup) => {
pickup.newLocation = event.target.value == -1;
}
},
});
which requires access to both the element in question and the object that was bound to that portion of the v-model.
By default, using v-on:change="locationChanged" calls locationChanged with the event, and the element can be reached via event.target but I couldn't find a way to access the pickup object I was binding the particular element to.
Using v-on:change="locationChanged(pickup)" instead causes locationChanged to be called with the model I need, but I then lose the reference to the HTML element in question.
What I ended up doing was setting up a local function in the model itself to forward the values:
v-on:change="e => locationChanged(e, pickup)"
which provides me with the information I need.
However, I feel that this is not the correct approach as a) I couldn't find it in the documentation, and b) it's not the most user friendly.
#Lawless pointed me to an existing question by another user who was wondering more generally how to access the event (as compared to my goal of accessing the event target, i.e. the element that triggered the event), but my question about the idiomatic approach here remains as this is a very basic question (callbacks for enumerated elements) and yet both solutions (mine and the linked question) are not very obvious and not covered in the vue.js manual.
Is there a more idiomatic approach prefered by the vue.js community?
Another question on StackOverflow (pointed out to me by #Lawless) was asking the same question I started off with (namely, how to access the event data in a binding for an enumerated element rather than one associated with a top-level vue.js object), providing another, more direct (but imho even more arcane) approach to accomplishing the same.
To recap, starting with an HTML element generated by vue.js bound to a vuejs object obtained via enumeration
<div class="card pickup" v-for="pickup in pickups">
<select v-on:change="locationChanged">
...
</select>
</div>
How do you access both the backing object (here, pickup) and a reference to the select element so you can query its new value and act accordingly.
My approach was to take advantage of the fact that vuejs passes in the event by default and work around the fact that vuejs suppresses the event parameter if you explicitly provide a local object as the parameter in the callback by using a lambda:
<div class="card pickup" v-for="pickup in pickups">
<select v-on:change="e => locationChanged(e, pickup)">
...
</select>
</div>
Explicitly adding the element I'm interested in to the callback, at the cost of an extra function call/layer of indirection.
The previous answer provided a solution that takes advantage of the explicitly defined vuejs $event variable, which is always translated to the native browser event, which can be directly used in addition to whatever other variables you wish to capture, making the solution look like this:
<div class="card pickup" v-for="pickup in pickups">
<select v-on:change="locationChanged($event, pickup)">
...
</select>
</div>
Which requires more intimate knowledge of vuejs, but avoids the closure.
However, I kept searching because it did not feel like this solution was in line with the vuejs ethos (and all I ever heard was everyone raving about how awesome the vuejs docs are, but this answer wasn't explicitly there but rather had to be pieced together).
It seems that I was grappling with a common case of knowing what I want but not how to get there.. and my previous domain knowledge that precluded vuejs led me to the non-idiomatic approach in my question rather than how I would have solved it if I started off learning frontend development with vue.js in the first place.
In the end, I found the obvious answer I was looking for, an answer that felt like it was the correct "vuejs way" of doing it and the proper idiomatic solution to my original question:
The problem is that I was intermingling standard JS/DOM introspection with the vuejs model, and the friction arose in the transition between the two (leaky abstractions and all). I wanted a native handle to the select element along with a vuejs object (pickup), when what I should have been doing was using vuejs exclusively to accomplish what I needed, ultimately by binding the select element to a vuejs object/property, and referencing that directly in my bound callback:
<div class="card pickup" v-for="pickup in pickups">
<select v-model:pickup.location v-on:change="locationChanged(pickup)">
...
</select>
</div>
With the select element now bound to the location property of my vuejs model, I can directly query its state/value in my locationChanged handler and pass in my pickup object without needing to use either $event or a closure:
let vuePickup = new Vue({
el: '#pickups',
data: {
pickups: pickups,
},
methods: {
locationChanged: (pickup) => {
pickup.newLocation = pickup.location == -1;
}
},
});

Angular2 function call from html element with no load event (or similiar)

I am new to Angular and have run into a problem that seems to have a javascript work around but they aren't very elegant.
I have a model with an array property. I ngfor the list property to build some html selection options. This is all working nicely. The problem comes when I am trying to set default value...the html elements don't have a load event.
I tried numerous html elements and they don't appear to have a load event either but I certainly could be doing it wrong.
I have seen a solution to put javascript tag right after the html and I could do that but I was really looking for a more elegant way in Angular.
I saw this SO post and thought that was my answer but there is a warning given that I agree with and thus it doesn't appear to be a good solution.
Regardless I tried it just to see if it would work and I got:
Failed to execute 'setAttribute' on 'Element': '{{loadDefaults()}}' is not a valid attribute name
<span {{loadDefaults()}} ></span>
So how can I fire an AS2 function in the component to load the default values?
HTML (btw this is NOT a full page load so there is no body tag):
<tr>
<td *ngFor="let loc of locOptions;">
<span>{{loc.text}}</span>
<input type="radio" name="radiogroup" [value]="loc.value" (change)="onSelectionChange(loc.value)">
</td>
</tr>
Edit
I thought perhaps mistakenly that ngoninit would fire too soon...before the html elements are rendered.
So perhaps what is being suggested is that I add a boolean is default to the model and bind THAT as the element is rendered.
In your ngonit function set this.locOptions to your default values. The value can be changed later on in any function and the change will be reflected in the view. Hope this helps you.
You should use ngOnInit to init you data, and call retrieve your data from your component :
defaults : any;
ngOnInit {
this.defaults = loadDefaults();
}
loadDefaults() {
//get data
}
HTML :
<span>{{defaults}}</span>

Angular2: undefined errors when trying to set focus to an input field using #ViewChild annotation

I have a input field which I set focus to when my view loads in the following way:
ngAfterViewInit() {
this.focusInput.nativeElement.focus();
}
this works fine from within the ngAfterViewInit() function but when I try to do it in another part of my view when a button is clicked I get an exception saying that focusInput is undefined. After reading up a bit it seems like ngIf could be the cause of this as the part of the view that contains the input field #focusInput gets shown or hidden using ngIf. Is there any way I can check using ngOnChanges() or anything else whether the #focusInput input field is currently shown and if it is set focus to it?
It happens when you have ngIf or ngFor directives inside your template and your input can not be linked to focusInput property you added inside your class. Instead use this code:
<input type="text" #myInput />
{{ myInput.focus() }}
Just add {{ myInput.focus() }} right after input inside template
The simplest solution turned out to be writing a custom focus attribute directive. This helped a lot:
How to move focus on form elements the Angular way
I know its very late to answer your question. If you want focus after any click or view change so for this you need to call change detector.
You can call change detection after your view change or a click by calling detectchanges().
`constructor(private detRef:ChangeDetectorRef) {}
#ViewChild('name_input') input: ElementRef;
private buttonClick(): void {
this.detRef.detectChanges();
this.input.nativeElement.focus();
}`
Hope this will helpful.

Passing a variable as a parameter to an ssrs report

I am trying to pass a variable from my classic asp page to ssrs. When I put in a literal value for the parameter, such as 296, it works fine. But I want to put in a variable that is sent by the URL so that it works in different ways for different people who are logged in. So, instead of a URL that is http://servername.net/reportserver....rs:Command=Render&Agency=296 (for the agency that is number 296) I want to use a variable that I have set to the agency of the person who has logged in. Let's say the variable is pAgency. I have tried Agency=" #pAgency (I set pAgency = to the logged in person's agency) and all sorts of other combinations, and have searched the web, but find no answer for this. I've even tried session variables but, no go. You must be able to do this but...
Thanks for any help you can give. Cheers!
That is not how a rest URI works to my knowledge. You need to build the string and present it first fully formed, not define a variable on it. You could do somthing in code like (using HTML Form as a base)
In the example below there are four clear things to understand:
A. The 'action' in the form must be the webservice location of a report and do a post to self. (Or you can do an iframe element potentialy but I have not messed with that as much)
B. The 'input' element is text based but you MUST match the id and name to the name of your parameter passing in.
C. The 'select' element gives a user 'option's of save methods to output directly to common types.
D. The 'input' for a type of 'submit' ensure the form will post to itself with the data prescribed.
<!DOCTYPE HTML>
<html>
<head>
<title>SSRS Tester</title>
</head>
<body>
<form id="SSRSRender" action="http:// (reportservername)/ReportServer?/(pathtoreport)" method="post" target="_self">
<H3>Enter some detail for the report to render</H3>
My Variable 'Test': <input type="text" id="Test" name="Test">
<br/>
My outputs:
<select ID="rs:format" name="rs:format" size=1>
<option value="HTML4.0">HTML 4</option>
<option value="IMAGE">Tiff Image</option>
<option value="PDF">PDF</option>
</select>
<br/>
<input type="submit" value="Render Report">
</form>
</body>
</html>
If you want to do more types of input variables to dynamically get SSRS to render as you want outside of the SSRS landing page you need to determine if you want to use:
The service with some front end with scripting like javascript with HTML
Something more easy to control will pre built tools like 'Report Viewer' with ASP.NET or a client application in C# or VB.NET
Create the service proxy yourself in a class library and do the calls in code directly as well as the formatting
Trying to create a rest URI programatically is better done by contacting the service and using built in methods IMHO rather than trying to make a string. It may be a little more of a learning curve but it will help you in the end.

When using HTML <select> tag, changed 'selected' value not displayed in Firefox

Hello (this is a copy of my post on the Seaside mailing list; first try at stackoverflow),
How do I get the rendered display of a drop-down select list to show an updated selection from another session, in Firefox? (I'm using 3.6.13)
This problem does not appear in Chrome, IE or Opera.
Here is the scenario: I have a domain object with an attribute displayed in a drop-down list. Some other session updates the attribute. I refresh my display, but the rendered selection does not change. Using Firebug, the generated html shows the updated selection. This may be basic HTML knowledge, but should the displayed value not update to show the changed 'selected' option? Or is the value intended to be set only on the initial page display and then only by a user action?
Example: I have a demo Seaside component with a class variable #testStateListSelection which is selected to 'one' in a Seaside session. If I change the value to 'three' in another Seaside session, the displayed value stays as 'one' in the original session after rendering again, even though the "selected" in the generated HTML shows "three".
renderSelectionListOn: html
html form: [
html select
list: #('one' 'two' 'three' 'four' 'five');
selected: self class testStateListSelection;
callback: [:value | self class testStateListSelection: value].
html break.
html submitButton
callback: [Transcript cr; show: self class testStateListSelection];
with: 'Save']
...the displayed value shows 'one', even though the HTML is...
<select name="1">
<option value="1">one</option>
<option value="2">two</option>
<option value="3" selected="selected">three</option>
<option value="4">four</option>
<option value="5">five</option>
</select>
How do I get the drop-down selected value to show 'three'?
BTW: all I know about HTML & browser behaviour I've learned from coding Seaside, so I may have a skewed perspective ;-)
Thanks for any help.
The problem is that, when you refresh your page, your browser is remembering which option was previously selected. This feature is designed to make it harder to lose your form data during long forms and is discussed a bit on the Mozillazine forums
Instead of refreshing the page. if you load the page "fresh" by going to the address bar and pressing return, you'll get the page loaded from the server again - with the updated select
Another cause of the problem might be that your browser tries to autocomplete the form for you based on your last submission. Make sure you have disabled this feature in the preferences of your web browser. You can also try to tell the form-tag with an unofficial attribute not to autocomplete:
html form noAutocomplete; with: [ ...
Whenever the page is refreshed the accessor self class testStateListSelection is run.
In fact the code you provide works perfectly for me. Are you sure that the accessors work as expected?
testStateListSelection
^ testStateListSelection " <-- forgetting the return is a common problem "
testStateListSelection: aString
testStateListSelection := aString
If using javascript to refresh the page...
window.location.reload();
...will NOT re-render the select elements. They will retain their dynamic values regardless of what the new source HTML says.
To force the select elements to re-render, use...
window.location.reload(true);