Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Sab669
Sep 24, 2009

Haven't touched Javascript since I took an Intro to JS course like 3 years ago; is there any equivelant to String.Empty from C#? Watching some tutorials for Unity and this guy tends to use a set of empty quotes frequently. Wasn't sure if there was a more "proper" way to get the same results.

Adbot
ADBOT LOVES YOU

Sab669
Sep 24, 2009

I was basically just told you should use String.Empty in C# because it's more "apparent" to someone else reading your code (or yourself in the future) what you're doing, where as just a set of quotes might imply to the reader something was left out. Or something.

I used to always just use the double-quotes all the time for appending non-strings to strings instead of the Convert class' ToString method, or use them when I just want an empty string until someone much smarter than I said otherwise :shrug:

Sab669
Sep 24, 2009

(Posting from my phone at work, sorry for poor formatting.)

TL:DRI'm looking for a JavaScript library to help iterate over HTML elements. Any suggestions?

I had to do something very similar to this in C# last week. I used HTML Agility Pack for this and it was fairly easy to use once I got the hang of it. For that project, I was iterating over a table and pulling out the InnerText; fairly simple. This time around it's a bit more complicated.


I've got a table within a div, within a table, within yet another table. So we're 3 tables deep. Thankfully (surprisingly) the div containing the table I care about has an ID so it's easy to find.

This final table has N rows and 4 columns. The number of rows is generated dynamically at run time to include a number of input controls to act as search parameters for the user.

I'm trying to basically combine the plain text in the "odd numbered" <TD> elements, then get the value of the control within the "even numbered" <TD> elements.

Now that I've typed it out it doesn't sound too hard but I can't figure out how to do it with just plain JS. I tried using document.GetElementById("myDivID"), then use getElementsByTagName to get the table, but this doesn't give me its child nodes (unsurprisingly). I tried passing "input" to that as well, but I'm getting far more controls in that collection than I can see on the page, which might be due to the third-party controls we use.

Sab669
Sep 24, 2009

jQuery's documentation for the .html() method states:

quote:

When .html() is used to set an element's content, any content that was in that element is completely replaced by the new content.

Is there any reason to do the following?

code:

var content = $("myDiv");
content.html("");
content.html(someVar);

I'm going to say no, but I wasn't sure if this is 'encouraged' to prevent any issues across browsers.

About a year ago my company's flagship application was rewritten to be brought out of the dark ages to be on par with what you might expect out of a web application 10 years ago instead of 15 :downs:

Looks like this year will be a slow year so I've just been going through everything and cleaning up all the garbage code written by the Indian code farm that churned this out. Finally finished with the server side code and now started the JS recently. I know it's only 1 line of code, but that's 1 extra live everywhere the software makes an ajax request... All adds up on the end. 12MB JS library, and any time we update the JS on the site users have to download the entire package :staredog:

Sab669
Sep 24, 2009

Lumpy posted:

I'm going to go out on a limb here and say they didn't do anything the "better way".

Generally a safe bet when it comes to these guys. I'm just far less experienced with JS than I am C# so I wasn't certain if there was, as I said, any "best practices" going on here.

Sab669
Sep 24, 2009

Noon on Monday and I'm done for the week already :suicide: So this isn't really a specific question but just a bizarre issue with IE11 that I'm looking for suggestions on how to debug this better.

It's an ASP.NET MVC application which uses Telerik's KendoUI controls.

I've got a page which has 25 fields and 2 buttons. Button 1 opens a search screen, button 2 opens another screen with the "base" 25 fields plus an additional 30. This screen can also open up the aforementioned search screen.

We've found a bug which only happens in IE when you open that "advanced" popup, then from there load the search screen.

This search screen has 3 grids. One grid lists "primary" codes for the user to select (via a radio button). When they select a record, an ajax request is made to populate the two child grids. These child grids have check boxes to select records from. So a user can select up to 1 record from the parent radio button grid, and any number of records from the child grids.

When they've selected the code(s) they want, they can click a button on this search popup and it will fill in the textboxes on the screen which opened this search popup.

The bug is that in IE, you open the advanced screen, open the search, click a parent grid item and click select to feed it back to the form. Click another parent grid item, select... When you click on the 18th code, the browser becomes unresponsive / stops painting.

No error logs, no output to the console, nothing in the Profiler / UI Responsiveness​ tab / Network tab indicates a problem. Whether I debug via Visual Studio or IE's dev tools to step through the JS the issue doesn't really happen; it's only when you "normally" use the software.

I have absolutely no idea what could be causing this :(

Sab669
Sep 24, 2009

I'm trying to build a list of unique strings and then compare another collection to that list. But I'm getting hung up on the "unique" part.

code:

function CheckSelection(gridName)
{
    //Get records from my grid control
    var view = $("#" + gridName).data("kendoGrid").data source.view();

    //Array to store unique values from a grid column
    var listOfGroups = [];

    //Integer to track the next index
    var listIndex = 0;

    for (var i = 0; i < view.length; i++)
    {
        //Check if the list already contains the 'GROUP' value from the current view record
        if (listOfGroups[view[i].GROUP])
            continue;

        //If the list does NOT contain the current record's value, add it
        listOfGroups[listIndex] = view[i].GROUP;

        //Increment the array index tracker
        listIndex = listIndex + 1;
    }
}

This grid has 3 rows, with the following GROUP values: "1", "1", "2".

I want my listOfGroups to contain 2 elements: "1", and "2".

The above code gives me three elements: "1", "1", "2".

The if statement never evaluates to true. I expected it to equal true on the second iteration, because "1" has already been added to my list.

If I use a breakpoint and try to evaluate listOfGroups["1"], I get undefined. So I think that's happening is that it's casting the string to an integer and then looking for the element at index 1, which does not exist.

So how can I check if my array already contains that value?

Sab669
Sep 24, 2009

I'm not sure if there's a solution to this problem, but I have an issue on a screen with 15 text boxes ("numbered" A-O). They can only accept values 1-7, 9, 10, or 88. (if they enter a single digit, we need to change it to be a 2-digit value prefaced with a "0", so 2 becomes "02")

If you enter 9, 10, or 88 in a few of the fields the software needs to disable a few other fields. If those other fields have values already then we need to present a pop-up confirming they want to clear out the fields.

So there's JS that runs both on key up and on blur to do the following:

* validate the value
* check if "child controls" have a value in order to prompt user
* update background color & tab indexes

The problem I'm experiencing is that it's very easy to be faster than the JS, so you just repeatedly hit tab and type in a value that will disable the child controls you can enter in values before the pop-up actually appears and now you're able to save invalid data.

Short of adding server side checks, is there some way I can do this? Is it possible to make the browser "wait" on the JavaScript to make sure everything finishes before they can move on to the next textbox?

Sab669
Sep 24, 2009

Chenghiz posted:

If it's important that the user's input is valid, you should be checking server-side, regardless of whether there is a problem in the client-side validation. Never trust the client for validation.

When the user inputs a value, is it posted to the server automatically, or do they have to submit a form?

I fully agree with you on the first paragraph, but unfortunately I'm not in the position to say "Hey guys our software is dumb as gently caress and we need to change all this" :(

Fortunately it's corporate software so we have some control over our users PCs (ie mandating JS) but yea I know it's not ideal.


They do have to manually post it to the server.

Sab669
Sep 24, 2009

Friday, fighting off a cold and just staring at this function for like an hour wondering why the gently caress it isn't working when my array has a single empty string in it:

JavaScript code:
function SubstituteTotalValues(controlArray)
{
	//If all elements are empty, do nothing
    if (controlArray.every((val, i, controlArray) => val === "" ))
        return controlArray;

	//Replace empty strings, dashes and values > 7 with a 1
    for (var i = 0; i < controlArray.length; i++)
    {
        if (isNaN(controlArray[i]) || controlArray[i] > 7 || controlArray[i] == "-")
            controlArray[i] = 1;
    }

    return controlArray;
}
The number of times I get burned by isNaN(someEmptyString) returning false is too drat high :sigh:

Edit: Actually I am in fact confused now?

http://jsfiddle.net/2na5wvbh/

Works exactly how I expect it to. But when I debug my application:



Element 3 doesn't have its empty value replaced? Debugging it, it does step into controlArray[i] = 1; but...?


Double Edit: OK it does actual work, but the Watch window is lovely and doesn't reflect this. If I mouse over controlArray in the actual code window I can see these values get updated.

Sab669 fucked around with this message at 21:36 on Jan 18, 2019

Sab669
Sep 24, 2009

Today I learned that Internet Explorer doesn't support arrow functions :argh:

Is there a simple, clean way to do this that works in all browsers:

JavaScript code:
if (controlArray.every((val, i, controlArray) => val === "" ))
    return controlArray;
Or do I need to just break it out like a CS101 student?

Sab669
Sep 24, 2009

Munkeymon posted:

Is

...

really so much worse?

No, not at all; I was dumb and thinking I needed to do it completely differently :downs: That'll teach me for copy-pasting StackOverflow answers

Sab669
Sep 24, 2009

Probably a simple question but can anyone tell me why projectedScore2 and projectedScore5 have a million decimal places?

https://jsfiddle.net/od1Lzn9e/

Math is hard :(

Sab669
Sep 24, 2009

Thanks


:argh:

Sab669
Sep 24, 2009

Cross posting from the web dev thread :(

Sab669 posted:

having some weird issue where a specific page in my software is loading scrolled half way down the page.

There are a bunch of different divs all sandwhiched on top of each other (dashboard / record navigation, then the actual scrollable div)

cshtml file is like so:
HTML code:
<div id="dvIntFup>
  <div class="wrap-box">
    <div class="a bunch of classes">
      <table>
        i know i know it's 2019 why the gently caress are you using tables; i didn't design it and I don't have the resources to unfuck it
      </table>
      <div id="divPageScroll" class="scrollarea">
        <table>
          a bunch of more table bullshit
        </table>
      </div>
    </div>
  </div>
</div>
<div id="divPageScroll" class="scrollarea"> is the div with the scrollbar (desired), but for some reason it starts out half way down the page (undesired).

In the document.ready we call SetContainerDimensions('INTERIMFOLLOWUP', '', 'divPageScroll');

JavaScript code:
function SetContainerDimensions(fromWhere, grid, dvContainer, dvBottomContainer)
{
	var windowHeight = $(window).height() - 1;
	if (dvContainer != null && dvContainer != undefined)
	{
		if ($('.dashboard').length > 0)
		{
			var innerWindowHeight = windowHeight;
			innerWindowHeight = innerWindowHeight - 50; // Header height;
			var bodyHeight = innerWindowHeight - $('.dashboard').height();
			bodyHeight = bodyHeight - 30;

			// for interim followup screen there is a html content above to scroll area.
			// Reducing the height.
			if (fromWhere == 'INTERIMFOLLOWUP')
			{
				//Mantis #16217 change 
				bodyHeight = bodyHeight - 112;
				fromWhere = '';
			}

			$('.scrollarea').height(bodyHeight);
		}

		containerProperty = dvContainer
	}
}
CSS code:
.scrollarea {
    overflow-x: hidden;
    overflow-y: scroll;
    height: 300px;
}
I've tried window.scrollTo(0,0); and document.getElementById('divPageScroll').scrollTop = 0; but neither change the behavior at all? :shrug:

Sab669
Sep 24, 2009

:sigh: Weird issue where I'm trying to just pass my form off to the server but 1 specific property isn't having its value set correctly for some unknown reason.

cshtml defines a checkbox bound to a Model property like so:
code:
@(Html.Kendo().CheckBoxFor(e => e.MiniFIM).Label("Perform PAC-CFI Assessment").HtmlAttributes(new { id = "chkMiniFIMIntFup", @tabIndex = "1", onclick = "PAIValidateMiniFim()" }))
Javascript uses some jquery ObjectToJSON function to convert the entire form to a JSON object that we then pass to the server with ajax:
JavaScript code:
var PAIIntFupAss = ObjectToJSON($('#frmPAIIntFupAss').serializeArray());
PAIIntFupAss.MiniFIM is "false", even though $("#chkMiniFIMIntFup").val() returns "true". I set a breakpoint on this line and see the checkbox has the epxected value, but yea the object gets a different value and I don't know why.

If I try to manually add PAIIntFupAss.MiniFIM = $("#chkMiniFIMIntFup").val(); on the following line, the C# throws an error along the lines of "MiniFIM is already defined" or something to that effect? Sounds like this assignment is adding a second 'key' named "MiniFIM" to the dictionary somehow :shrug:

If I add a watch for $('#frmPAIIntFupAss') I can expand it, find my checkbox, and it has the value true / name is MiniFIM so ObjectToJSON should be working correctly? I have no idea what's going wrong.

And that is the only control bound to that property :downs:

Sab669 fucked around with this message at 21:12 on Jul 25, 2019

Sab669
Sep 24, 2009

Page Inspector gives me this:

Checked

<input checked="checked" class="k-checkbox" id="chkMiniFIMIntFup" name="MiniFIM" onclick="PAIValidateMiniFim()" tabindex="1" type="checkbox" value="true">
<label class="k-checkbox-label" for="chkMiniFIMIntFup">Perform PAC-CFI Assessment</label>
<input name="MiniFIM" type="hidden" value="false">


Unchecked:

<input checked="checked" class="k-checkbox" id="chkMiniFIMIntFup" name="MiniFIM" onclick="PAIValidateMiniFim()" tabindex="1" type="checkbox" value="true">
<label class="k-checkbox-label" for="chkMiniFIMIntFup">Perform PAC-CFI Assessment</label>
<input name="MiniFIM" type="hidden" value="false">


So actually, that's really curious. I assume it's pulling the value from this hidden Input rather than the checkbox? But this checkbox is defined identically to another checkbox on a different form that basically does the same thing :sigh: Literally the only difference is the ID and the onclick (which just shows a popup, then clears some textboxes if they click YES, does nothing / unchecks the checkbox if they click NO)

Sab669 fucked around with this message at 14:16 on Jul 26, 2019

Sab669
Sep 24, 2009

Munkeymon posted:

are you looking at the live DOM or viewing the source?

Live, I guess? Run the software -> Hit F12 -> Inspector tab (Firefox)


The hidden input must be some Telerik/Kendo nonsense. I definitely didn't manually define it myself.

code:
<td>
	@(Html.Kendo().CheckBoxFor(e => e.MiniFIM).Label("Perform PAC-CFI Assessment").HtmlAttributes(new { id = "chkMiniFIMIntFup", @tabIndex = "1", onclick = "PAIValidateMiniFim()" }))
</td>
Is the "full" declaration for that checkbox within its parent table data element. Those 2 inputs and the label from my previous post are all found within the <td> I defined when I pull up the Inspector.

Sab669
Sep 24, 2009

Hey dumb question - I just started a job yesterday that uses Angular, which I've never even so much as looked at before yesterday. I'm following along with the shopping cart tutorial on angular.io and on a previous step they had me add:

code:

[routerLink]="['/products', product.id]"

to an anchor tag.

On this step I'm up to now, the syntax they tell me to add to a button is:

code:

routerLink="/cart"



Why the brackets for the attribute / value in the first example and not the second? Does it not really matter and it's smart enough to infer what was meant?

Sab669
Sep 24, 2009

Oh OK, so the routerLink "attribute" only needs them if the value justifies it, essentially?

Sab669
Sep 24, 2009

EDIT :toot: figured it out. You can refer to an object's fields through a string like so: theObject["propertyName"], so in my case my ckeditor definition simply needed to be <ckeditor [(ngModel)]="asrModel[field.modelProperty]" ..>

For lack of a better term, does Angular support reflection? Like I want to use the value of oneObject.SomeStringProperty to get the actual value of otherObject.TheActualPropertyIWant
I don't know if what I'm trying to accomplish is technically possible.



Right now, I've got a hardcoded rich text editor bound to a property on my object, which gets loaded onInit.

component.HTML:
code:
    Special Considerations:
    <div>
        <ckeditor [(ngModel)]="asrModel.specialConsiderations" [editor]="Editor" (ready)="onReady($event)">    
      </ckeditor>
    </div>
component.ts:
code:
export class AsrGenerationComponent extends Base implements OnInit {
  public asrModel: AsrModel = new AsrModel();
  
  ngOnInit(): void {
    this.getAsrData();
  }

  getAsrData(): void {
    this.asrService.getDataByLoanNumber(lnum).subscribe(l => {
      if (l){
        this.asrModel = l;
      }
  }
}
That's a really stripped down version of the whole component, but I think you get the idea; I'm fetching data for my asrModel object and the ckeditor is bound to a property on that object. This all works. Page loads, I see asrModel.specialConsiderations's value in my control.


What I'm trying to do now, instead of hardcoding my UI is just load a JSON object that defines a collection of Sections, which has a collection of Subsections, which has a collection of Fields.
That got that working, but I can't abstract out the `[(ngModel)]="asrModel.specialConsiderations"` of the HTML shown in my first snippet above into my JSON.

My field JSON looks like this:
code:
						"fields": [
							{
								"headerDisplay": "Special Considerations",
								"subHeaderDisplay": null,
								"name": "Special Considerations",
								"fieldType": "textField",
								"objects": null,
								"defaultValue": "Enter Name...",
								"fieldFormatting": "text",
								"initialDataSource": null,
								"isPreselected": false,
								"formControlName": "documentName",
								"canEdit": true,
								"modelProperty": "asrModel.specialConsiderations"
							}
						]
It's just a very generic definition of most input controls on a web application so that if we need to print a textbox, radio button, drop down, date picker etc. we can define all that here.

And my updated component.html:
code:
            <!-- loop over the Fields collection seen in my JSON above^-->
            <div *ngFor="let field of subSection.fields" style="margin-left: 15px;" [ngSwitch]="field.fieldType">

              <!-- switch on the fieldType value from the JSON to determine what kind of control to render -->
              <div *ngSwitchCase="'textField'" style="margin-left: 20px;" class="form-group">

                <!-- parse the field data>
                {{field.headerDisplay}}
                <p *ngIf="field.subHeaderDisplay != null">{{field.subHeaderDisplay}}</p>
                <div>

                  <!-- this is the line I'm having trouble changing from my first HTML snippet -->
                  <ckeditor [(ngModel)]="field.modelProperty" [editor]="Editor" (ready)="onReady($event)">
                
                  </ckeditor>
                </div>
              </div>
The output of this is that my ckeditor control renders the literal string text "asrModel.specialConsiderations", whereas I simply want to use that as a reference to go get the specialConsiderations field from my asrModel object.

I hope that all makes sense :( Like I said I'm pretty new to Angular, I strongly suspect it's possible I just don't know how / can't find it on SO.

Sab669 fucked around with this message at 17:33 on Mar 10, 2022

Sab669
Sep 24, 2009

I've never used this, but https://recogito.github.io/annotorious/ looks like it might fit what you want.

I've used image annotation packages for a C# project a long time ago. Forget how it all works, but I recall it being pretty easy to just overlay text dynamically onto an image.

Sounds like you're trying to "stack" layers images on top of one another though rather than text? What exactly do you mean by "markers"

Sab669
Sep 24, 2009

Has anyone encountered this error before?

quote:

Failed to compile.

./node_modules/ngx-extended-pdf-viewer/fesm2015/ngx-extended-pdf-viewer.mjs 3936:15510-15522
Can't import the named export 'AsyncPipe' from non EcmaScript module (only default export is available)

I'm trying to install this library, I tried both their Recommended Way and got the above error. Then I tried their Angular CLI steps but as soon as I add the imports to my app.module.ts I get the above error.

I've googled around a bunch and I see lots of posts with similar errors but a different export, and all the solutions seem specific to the whatever library that specific post is about.

Sab669
Sep 24, 2009

Thanks, although I have no idea how to do that :v: Looking into it now, definitely seems like a problem for Monday though.

Sab669
Sep 24, 2009

I'm not even sure how to articulate this, but basically I'm wondering if it's possible to "instantiate" an Angular component from a string? Like if I have a component:
code:
@Component({
  selector: 'app-title-page',
  templateUrl: './title-page.component.html',
  styleUrls: ['./title-page.component.css']
})
Then in my main app.component.ts I declare this variable:
code:
public titleComponent: string = "<app-title-page>";
And in app.component.html I have:
code:
<div>
	{{titleComponent}}
</div>
But that just prints out the literal string.

I've also tried:
code:
<div [innerHTML]="titleComponent"></div>
But this just gives me a blank page :(

I feel like this has to be possible but my GoogleFu is failing me

Sab669
Sep 24, 2009

That sounds like what I'm looking for, yes. Thank you.

Sab669
Sep 24, 2009

So this is definitely feels like a dumb question but... My angular app is consuming some API endpoint (C#) that returns a List<Dictionary<string, string>> and I don't really know how to handle this type in Javascript? :downs:

The List contains 2 dictionaries, which I wish to present in 2 columns in a table. One column will be user-editable data, the other column will be some static display coming from another system. The first dictionary contains the editable data (if any), and the second dictionary is the static values.

I have this code:

code:
  userInputValues: string[];
  staticValues: string[];

  ngOnInit(): void {
    this.getArray(this.inputArrayName).subscribe(arr => {
      if (arr){
        this.userInputValues = arr[0];
        this.staticValues = arr[0]; // ***this is the problematic line but I don't know why the "obvious solution" doesn't work***
      }
    });


  getArray(model: string): Observable<[[]]>
  {
    let serviceUrl = this.baseServiceUrl + '/get-array/' + model;

    return this.http
      .get<[[]]>(serviceUrl, this.getHeaders())
      .pipe(catchError(this.handleError<[[]]>('getArray', null)));
  }
And in my component html:

code:
    <tr>
        <td>Terminal Cap Rate</td>
        <td><input type="text" id="txtAtQuote1" name="txtAtQuote1" [(ngModel)]="userInputValues['exit_terminal_cap_rate']" (ngModelChange)="update()"></td>
        <td>{{this.staticValues['exit_terminal_cap_rate']}}</td>
    </tr>
The above code works enough, but there is a problem in my ngOnit at the top, as the comment says. It "should be" this.staticValues = arr[1]; instead of [0], but doing that throws a compile time error: "Tuple type '[[]]' of length '1' has no element at index '1'" which doesn't make sense to me because how could it possibly know the length at compile time?

So essentially the question is, how do I access the second dictionary from the object returned by my API?

Sab669 fucked around with this message at 19:26 on Aug 4, 2022

Sab669
Sep 24, 2009

I wasn't really sure how to define just like an array of arrays, or an array of generic objects.

I say generic because that getArray function is actually just living in some service and is going to be used by... probably dozens of different components, returning Lists of a variable number of dictionaries with god knows how many keys depending on whatever the array name passed in is -- so I was trying to avoid actually creating some sort of object with actual properties for me to reference in my component/HTML.


So, yea, changing it to `any` works perfectly :toot: thanks

Sab669
Sep 24, 2009

Good point. I guess I'm just so ingrained in working in more strictly typed languages all my life :v:

Sab669
Sep 24, 2009

Well. It's hard to give a concise answer to that, and I do agree it felt pretty "smelly" when I was first introduced to this List<Dictionary<>> aspect of our database a month or two ago (and still does :v:). But unfortunately it's way too big of an org for us to just go change poo poo like that and it would have implications for dozens of other applications downstream.

But basically we have this concept of "array fields" which I think was implemented to track groups of data through time, although I don't really know who came up with this structure or why. But for example say we've got these 4 tables:

- Property
- ArrayTypes
- ArrayFields
- ArrayData

One of the "ArrayTypes" is "Expenses".
The "ArrayFields" for "Expenses" might be "Taxes", "Maintenance", "Administrative Fees", "Utilities" and whatever else you can imagine costs a property owner money. Then the ArrayData table would contain the actual values, and the IDs for the Property & ArrayFields. Those Array tables are recycled for all manner of objects, not just properties, and the values aren't always going to be numeric. But either way, this lets us just insert another row into the ArrayFields without having to add another column to a table and then update all of the objects code-side to account for this new field/row.

So we're basically just saying "Give me all the <ArrayFields> of <ArrayType> for <Property>"... Except we're not only getting 1 collection of fields/data, we're getting N collections with historical data & predictive data for the future -- and that is why it's a List of Dictionaries, where the key/value pair is the array field name and the array data. And each dictionary in the list would be the data for that array as it was 2 years ago, 1 year ago, current year, +1, +2 years or whatever.

And lastly... Pretty much all of our applications are more or less being written to be config driven so we almost never need to actually push code changes. So while my HTML example in my original post does hard-code the dictionary keys/object properties, that won't be the case soon -- it'll just be more like "[(ngModel)]="userInputValues[arrayFieldNameFromConfig]". Then when we add a new row to the ArrayFields, all I'd need to do is just update this config file with the input type (date, text, number, label, whatever) and the array field name and the app will automagically handle it all.


I'm not saying it's the best solution for the problem, especially when I'm not even sure "tracking groups of data through time" was the exact problem that resulted in this implementation, but it's what I'm stuck with so :shrug:

Sab669 fucked around with this message at 21:58 on Aug 11, 2022

Sab669
Sep 24, 2009

But again the thing we're trying to avoid is that if we go and add a new row to the ArrayFields table then we don't want to have to go and update our hardcoded model with a new field and then have to deploy that code. By making it all "config driven" we're just updating some JSON in Azure somewhere and then the app will immediately reflect those changes.

We have dozens of these "array types" with dozens of "array fields" each that my app will have to support, whether I manually create them all or somehow just write some script that generates the files/classes for me is still going to add a lot of stuff that would need to be maintained in the future.

Sab669 fucked around with this message at 01:05 on Aug 12, 2022

Sab669
Sep 24, 2009

The thing is though is that the HTML is basically just a giant for loop that does little more than print out a collection of tables and input controls that all automatically get force fed back to the API which does all the validation. So I'm really not writing much, there's nothing to read, there's virtually nothing to write incorrectly. It's an extremely thin client that just looks at that config file to know what the app should look like and how to send/receive some arbitrary collection of data.

If I've been working on this project for 3 months, the majority of that time has just been building out that config file with some small amount of development time bending CKEditor to our will, and getting acquainted with the API we use to get/pass data from our DB. And now dicking around with these "array fields" that are a beast of their own and weren't present in the first 2 sections of the application.

Sab669 fucked around with this message at 02:14 on Aug 12, 2022

Sab669
Sep 24, 2009

Quick question: what's the easiest way to call a function when a div scrolls into view?


End users want a giant single-scrolling app, "like the Word document we use that this app is based off of", so I implemented a single accordion style menu that they can click on and it'll scroll them to the appropriate section of the page using this code:

code:
<span role="button" (click)="updateSelectedChildTab(section.index, subSection.index)">
	{{subSection.sectionHeader}}
</span>

updateSelectedChildTab(parentTabIndex: number, childTabIndex: number): void
{
	if (parentTabIndex != null && childTabIndex != null && this.isDataLoaded)
		document.getElementById('div' + parentTabIndex + childTabIndex).scrollIntoView();
}
When the user clicks on an item from the menu, I apply a style to shade it -- but I'd also like for this styling to get applied as the user manually scrolls through the app, highlighting the appropriate nav menu items as they scroll in & out of each. All I need is to basically just pass in the div name of the one coming into view as that would have the "coordinates" for me to find the correct accordion item to highlight.

Sab669 fucked around with this message at 18:30 on Dec 15, 2022

Sab669
Sep 24, 2009

Obfuscation posted:

Check the position of the screen after scrolling and compare it to element positions, something like this.

:toot: Thanks!

Sab669
Sep 24, 2009

I'd recommend just looking up like "Intro To X" or "Crash Course On X" where X is the framework/libraries you'll be using (React / Angular or whatever) or environments it'll be running in rather than just like "Javascript how do I X" where X is some common thing that virtually every language can do but just does differently.

Sab669
Sep 24, 2009

Dumb Angular Question - and I'm phone posting so the code will be minimal, sorry.

Essentially what I'm trying to do is dynamically loop over a collection of data and print out an HTML table with different types of user input controls.

That all works well and good, but now a new requirement came in to also optionally show some checkbox next to the input control.

code:

<td *ngFor="let cell of row.td">
  <div [ngSwitch]="cell.inputType"
    [style.width.%]="cell.canBeNA ?? 80">

    <span *ngSwitchCase="'Currency'">
      <!-- HTML for a numeric input with some currency mask-->
    </span>

    <!-- repeat above span for a bunch of different input types-->
  </div>

  <div *ngIf="cell.canBeNA" style="width: 20%">
    <!-- HTML for a checkbox-->
  </div>
</td>

I have that dynamically being added in easily enough, but the problem is my first div takes the full width of the TD and then the checkbox appears on a new line beneath it. We'd like to instead shrink the input so the textbox and the checkbox are on the same line.

When I inspect the HTML while running my app, that first div inside the TD doesn't have a "style: width" attached at all. And I have no idea why, because "cell.canBeNA" evaluates just fine when deciding to show my checkbox :shrug: Any idea what stupid thing I must be overlooking?

Adbot
ADBOT LOVES YOU

Sab669
Sep 24, 2009

The Merkinman posted:

Can I have a type for row.td?
What is canBeNA? a boolean? is it an optional boolean?
right now cell.canBeNA ?? 80 will return either the value of cell.canBeNA or 80, which I don't think is what you want.


Also if you're using Angular 17, you should use the Control Flow syntax, not that it's required to solve your issue.

EDIT: I'm going to assume you should replace [style.width.%]="cell.canBeNA ?? 80" with something more like [ngStyle]="{'width' : cell.canBeNA ? '80%' : null}"

row.td is just some collection of a custom class which spells out all sorts of stuff like labels, input types, colspan and rowspan and input masking and sorts of attributes associated with an HTML table, generally.

But yea, canBeNA is a bool and you're right that it was mostly just a syntax error. This seems to have done the trick:

[style.width.%]="cell.canBeNA ? 80 : auto"

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply