Can node property dialog use data from config node property?

If you can post a link to your repository I can take a look. There would be far too much speculation to try and determine the cause of your current problem without a code review.

@Steve-Mcl : GitHub - Joe-ab1do/MCP23017-PCF8574-AIO: This is a Node-Red node to communicate with MCP23017 or PCF8574(A) chips on a I2C bus. Both Input + Output.

This is a fork from @PizzaProgram 's code, on which I have been building. By far, most of the work has gone into the HTML file. The code is very much in a development stage. I cloned the forked code using vscode and saved it do a directory on my RPi. For some reason the node will not install from that directory (outside ~/.node-red directory) with npm. Probably something to do with package.json (haven't even started looking at that yet), so every time I make a change I commit to my repository and install from there, which works fine.

Anyway, thanks for taking the time. Any help is much appreciated :slightly_smiling_face:

When developing, you can simply do an npm install /path/to/yourcode and npm will create the proper package.json entry for you. Don't forget to restart node-red after making changes to your code though. And don't forget to reload the Editor page if you've made changes to the node's .html file.

To clarify, that install only needs doing once. You will see that the package.json contains a file: entry instead of the package name.

1 Like

As far as I know, it is NOT enough to do it once, after that you need to REBUILD always, if you change the html code. (At least on NR 2.x, I don't know about 3.x yet.)
You must do always:

  1. Go to the source directory of the node (NOT to .node-red, but your own dir.)
    cd ...\MCP23017-PCF8574-AIO

  2. npm install MCP23017-PCF8574-AIO --offline ... once done, than always:
    npm rebuild MCP23017-PCF8574-AIO --offline >> so REBUILD it

  3. node-red-restart (or start debugging again)

  4. reload the browser. (best with Ctrl+ F5 to have a full reload)

@TotallyInformation : Thanks. That's what I actually tried, but did not know that npm install will create the proper package. So I should first delete the package I cloned right? What about package-lock: delete also? The code resides in ~/dev/MCP23017-PCF8574-AIO. To install it I tried cd ~/.node-red/ and then ran npm install ~/dev/MCP23017-PCF8574-AIO. Restart node-red and reload browser editor. However it never worked, but could be the issue with the cloned package (and package-lock). I'll give it a shot.

@PizzaProgram : Thanks, I might just try that if just installing after deleting package doesn't do the trick. --offline switch is also new to me. This is the first time I've come across that. Do you think it is key? First offline install only, or every time when I want to test a change? Good to know about npm rebuild also, just in case nothing else works.

FYI, I use NR3.x on a RPi4 with vscode running on a Windows machine ssh to RPi4 and linked to my github repository. After any new code install I always restart node red and reload the browser editor, so that can't be it.

One thing I noticed is because the project is scoped, it installs into a node_modules directory named @xxxxx. Using palette manager to uninstall the node empties this directory, but does not remove it, as it does when uninstalling a non-scoped directory. Very minor issue, to say the least, just thought I'd mention it.

it does NOT copy the files to .node-red directory, just creates a simlink from your deveroper folder.
Always make backups from your dev folder. (zip it). I've lost my once or twice while I was testing re-/intall of my package.

Not the case on Windows anyway, this is how I always develop my nodes and I never need to rebuild or reinstall. The install of a folder creates a local install. All you need to do is restart node-red if you changed anything and reload the editor if you changed the html file. Been doing that for some years now.

AFAIK, rebuild is only needed in those cases if you made a change to a C++ component. And even then I would expect a simple make of the binary would be enough for a local install though I've not tried it.

Actually, you don't probably need to remove the other package but it is probably safer.

I generally delete that though actually an install should rebuild it anyway. I've had lots of problems with the lock file over the years and it is mostly useless for node-red use anyway since most people don't try to distribute their userDir folders without doing an npm install on the new target. The lock file is only useful for distribution of a complete node.js application where you need to guarantee an exact set of package versions.

Certainly on Windows, you don't need to use --offline. You will sometimes see people also recommend using the link command but that does some very strange things and seems unnecessary - certainly on windows anyway where I do most of my development.

That is interesting. The scope comes from the name field in the package.json file of course and isn't used if you do a local install though npm still understands the scope when installed.

And that's possibly the difference from a local install. In the example I gave, no simlink is required and it all just works. A local install uses the folder specified - which has to be the folder that contains your node's package.json file of course. You will see it in the userDir package.json.

I had serious issues on Windows when using npm link in the past, it creates a very odd indirection. Never ever had problems on Windows by doing a local install.

There is, however, one slight oddity and that is how your packages (your node package that is) handles its own required packages. With the way I suggest, you need to do an npm install in your node's package folder to get the requirements installed whereas live code will install them into your userDir. Mostly this makes no difference at all unless, like some of the uibuilder code, you are automating npm package handling.

So here is a summary of my dev workflow:

  1. Create a new repository on github
  2. Clone that repo to a local folder (I use c:/src/... on Windows but anything will work)
  3. Create the basic files in your local repo clone folder including the package.json file
  4. In your userDir folder (typically ~/.node-red), do npm install /path/to/clone
  5. Restart node-red (and reload the Editor page if needed).

Then continue to develop your node and repeat step 5 when you want to test it.

Obviously, use git to commit changes as you go along and use git push to update the GitHub repo.

Once complete, create a new git tag and push the tag to GitHub then use npm publish to update the npm registry when you want everyone else to be able to use it. Finally tell the Flows site to update as needed.

Here is an example from my dev PC:

  "dependencies": {
    "@node-red-contrib-themes/theme-collection": "^3.0.1",
    "@totallyinformation/node-red-experimental-nodes": "file:../../node-red-experimental-nodes",
    "chokidar": "^3.5.3",
    "collection-red": "~0.0.5",
    "csv-parser": "^3.0.0",
    "ejs": "^3.1.6",
    "fast-glob": "^3.2.11",
    "fs-extra": "^10.0.1",
    "googleapis": "^105.0.0",
    "mqtt": "^4.2.8",
    "node-drayton-wiser": "file:../../node-drayton-wiser",
    "node-red-contrib-cron-plus": "~1.5.4",
    "node-red-contrib-events": "file:../../node-red-contrib-events",
    "node-red-contrib-jktesting": "file:../../node-red-contrib-jktesting",
    "node-red-contrib-simple-gate": "~0.5.2",
    "node-red-contrib-telegrambot": "^12.0.0",
    "node-red-contrib-uibuilder": "file:../../node-red-contrib-uibuilder",
    "node-red-dashboard": "~3.1.7",
    "node-red-node-discord": "~2.2.0",
    "node-red-node-random": "~0.4.0",
    "node-red-node-sqlite": "~1.0.3",
    "red-contrib-drayton-wiser": "file:../../node-red-contrib-drayton-wiser",
    "wmi-client": "^0.5.0"
  },

Very helpful, thanks. Items 1. and 2. done; re item 3. including the package.json file: this is a little confusing, as I thought that you said that npm install in the ~/.node-red folder would create the package.json file?? If there is already one (the cloned package) in the /path/to/clone folder it doesn't create a new one. That I know for sure.

I could just give it a try and see what happens if I first delete the cloned package and package-lock files, but I have frozen NR once already to the point of having to totally reimage the uSD card (luckily I had a clean image including NR ready to go - just takes up a lot of time). Nice thing about working off the repo is that I had a back-up of the node files there, but I feel I am kind of abusing the repo a bit and would love to just develop and test locally first, before comitting.

Sorry. You need to understand that every npm "package" is defined by its own package.json file. Step 3 refers to your custom node's repo folder. If it doesn't already have its own package.json, you need to do npm init in the folder. You can then install any dependencies that your custom node may need. into that folder using npm install xxxxx and the package.json file will be updated accordingly.

This is different to the package.json file in your ~/.node-red folder which defines the packages that provide your custom nodes.

It is easier if you do a bit of reading about how npm works to be honest. It is confusing to begin with due to the mix of hierarchical and flat package structures that npm creates. But you'll soon get your head around it.

No, the node-red install creates a package.json file in ~/.node-red, that contains the definitions of your installed nodes (each of which is defined by an npm package as described above).

OK, so you can simply npm remove packagename to remove the one you had before and then npm install /path/to/clone

Just to add a bit of complexity for you :slight_smile: - if you don't happen to have a separate device to do your development on (which I have to say is much easier - I have my daily-driver PC where I develop and a Linux server for my "live" node-red and other stuff). You may wish to look at my alternate installer repo. This lets you install local copies of node-red and makes it easy to have completely isolated instances of node-red. They can even run on different versions of node-red which can be very helpful when a new major version is in testing. Since node-red is "just" a node.js application, you can install it locally rather than globally. In my view that is more secure anyway.

Thanks for the additional info and clearly I still have much to learn about packages. I read through the section on packages in the npm documentation as suggested, but not quite sure I understand it all at first glance. I actually do have a separate development device, the RPi I mentioned, which is one of several I have. This one is exclusively used for development, so if I break anything, it doesn't effect anything else. So yeah, I had to reimage the uSD card, but nothing "critical" was effected, just lost time.

Really do appreciate all the help in this area, but I feel we are getting more and more off topic here from my original issue of not being able to use the config node's settings the first time after an instance of it is created.

I'm going to continue on installing from development folder. I know I said I felt it was getting off topic (and I would really get back to my original issue), but I now have it working :slightly_smiling_face:. The key was

I removed the package-lock file and created a new package file in my cloned repo folder. The package has one dependency (i2c-bus), so I had to npm install i2c-bus into my cloned repo folder, which created a node_modules sub-folder. Then changed to .node-red directory, npm installed directly from my cloned repo folder, then node-red-restart, reloaded browser page and all worked fine. The key was the NR module that I installed was missing the i2c-bus node module.

However in the ~/.node-red/node_modules directory there already is an i2c-bus module and I now have the same module in ~/.node-red/node_modules/my_NR_node_module/node_modules folder, which is a duplicate of the one already installed. So my question now is: Can I avoid this duplication of 12c node_modules? I feel like in my package file I would need to point to the i2c-module already available in Node Red.

Don't stress, when you see a live install, the duplicate won't be there. It is just an artifact of the way things are installed during development.

Feeling better already :sunglasses:

Back to the original topic then: being able to use the settings in the config node to prefill the select options of a dropdown list on the main node's properties dialog.

Through debugging and using a number of console.log() statements, I have been gradually able to figure out what is going on, but don't know how to resolve the issue.

In the oneditprepare section of the node I refer to a config node using the statements

const node = this;
			var chip = RED.nodes.node($('#node-input-chip').val());
			var chipName = chip.chipType;

where $('#node-input-chip') refers to the html input tag holding the list of instances of the config node. When there are no instances of the config node, e.g. on first use of the node
var chip = RED.nodes.node($('#node-input-chip').val()) (chip object) is undefined (as would be expected). Clicking on the edit button opens the config node dialog, where settings such as chip type, i2c bus number, i2c address can be entered. Clicking on the Add button then closes this config dialog to return to the node's properties dialog. The newly created configuration shows in the list of configurations and the config node shows up in the editor. So far so good. However in the node's oneditprepare section there is also an a change event:

$('#node-input-chip').on("change",function(d) {
				console.log("onChange event fired");
				updatePortList();
			});

which does not fire, despite the fact that $('#node-input-chip') has changed. When clicking on Done the properties dialog closes. Double-clicking on the node reopens the properties dialog, chip object is now defined and the change event fires before the properties dialog is shown. GREAT!

Selecting Add new configuration from the configuration dropdown list shows chip object again as undefined. Click on edit to add new configuration and then click Add again returns to the node's properties dialog where the new configuration shows in the dropdown list. However, unlike before, the change event fires. From this point on new configurations can be added, each time firing the change event.

So the change event does not fire when the very first config node is created. It is almost as if I need to either use a different kind of event (I have tried .trigger("change") event, but to no effect), or somehow catch the fact that no previous instances of the config node have been created, but after much searching I am at a loss.

I have gone over the MQTT code (which shows similar behavior when protocol 5 is selected or not) many times figuring the solution must be there somewhere, but there is just too much detail in that code to see the big picture of what is happening. If someone can point me in the right direction, that would be great.

Worked it out. The key was to refer to RED.nodes.node($('#node-input-chip').val()) object only within the updatePortsList function and test if it is undefined, in which case chipName is given a default name. If not undefined, then it equals the .chipType property of the object. So it is now finally working as expected :slightly_smiling_face: . I'm sure there are better/more efficient ways to do what I want, but for now it does the trick.

Thanks to all those who nudged me in the right direction. Moving on to next item on my todo list.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.