Hi, I want to learn plugin development, and I am following the knockout tutorial to create a button that can change text to upper case: Knockout tutorial - Introduction lesson 5 of 5
I have to variables:
some_text and max_diff
I want to set both variables in setting view, then display them in tab view.
I also created a button to change the text value to all cap.
So far, I can only display the value of max_diff in the tab view, but it doesn't work for "some_text".
What did I do wrong?
I created a test plugin, with following structure:
OctoPrint-TestPlugin
OctoPrint-TestPlugin
static
css
TestPlugin.css
js
TestPlugin.js
less
templates
TestPlugin_settings.jinja2
TestPlugin_tab.jinja2
__init__.py
Content of "_ _ init _ _.py"
# coding=utf-8
from __future__ import absolute_import
### (Don't forget to remove me)
# This is a basic skeleton for your plugin's __init__.py. You probably want to adjust the class name of your plugin
# as well as the plugin mixins it's subclassing from. This is really just a basic skeleton to get you started,
# defining your plugin as a template plugin, settings and asset plugin. Feel free to add or remove mixins
# as necessary.
#
# Take a look at the documentation on what other plugin mixins are available.
import octoprint.plugin
import logging
class TestPlugin(octoprint.plugin.StartupPlugin,
octoprint.plugin.TemplatePlugin,
octoprint.plugin.SettingsPlugin,
octoprint.plugin.AssetPlugin,
octoprint.plugin.SimpleApiPlugin,
):
def __init__(self):
self._logger = logging.getLogger("octoprint.plugins.Test")
self._logger.info("this is Test init func")
def on_after_startup(self):
self._logger.info("### Test Plugin ###")
self._logger.info("### Test Plugin max_diff: %s" % self._settings.get(["max_diff"]))
##~~ SettingsPlugin mixin
def get_settings_defaults(self):
return dict(
# put your plugin's default settings here/
max_diff=1, # some variable for playing around
some_text="abcdefg", # some text variable for playing around
)
def get_template_configs(self):
return [
dict(type="settings", custom_bindings=False),
dict(type="tab", custom_bindings=False)
]
##~~ AssetPlugin mixin
def get_assets(self):
# Define your plugin's asset files to automatically include in the
# core UI here.
return dict(
js=["js/Test.js"],
css=["css/Test.css"],
less=["less/Test.less"]
)
def gcode_processor(self, comm, line, *args, **kwargs):
if "MACHINE_TYPE" not in line:
return line
from octoprint.util.comm import parse_firmware_line
# Create a dict with all the keys/values returned by the M115 request
printer_data = parse_firmware_line(line)
logging.getLogger("octoprint.plugin." + __name__).info(
"Machine type detected: {machine}.".format(machine=printer_data["firmware_name"]))
return line
# If you want your plugin to be registered within OctoPrint under a different name than what you defined in setup.py
# ("OctoPrint-PluginSkeleton"), you may define that here. Same goes for the other metadata derived from setup.py that
# can be overwritten via __plugin_xyz__ control properties. See the documentation for that.
__plugin_name__ = "Test"
# Starting with OctoPrint 1.4.0 OctoPrint will also support to run under Python 3 in addition to the deprecated
# Python 2. New plugins should make sure to run under both versions for now. Uncomment one of the following
# compatibility flags according to what Python versions your plugin supports!
# __plugin_pythoncompat__ = ">=2.7,<3" # only python 2
# __plugin_pythoncompat__ = ">=3,<4" # only python 3
__plugin_pythoncompat__ = ">=2.7,<4" # python 2 and 3
def __plugin_load__():
global __plugin_implementation__
__plugin_implementation__ = TestPlugin()
global __plugin_hooks__
__plugin_hooks__ = {
"octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information,
# "octoprint.comm.protocol.scripts": __plugin_implementation__.message_on_connect,
"octoprint.comm.protocol.gcode.received": __plugin_implementation__.gcode_processor,
}
Content of "TestPlugin.js"
/*
* View model for OctoPrint-TestPlugin
*
* Author: tester
* License: AGPLv3
*/
$(function() {
function TestPluginViewModel(parameters) {
var self = this;
// assign the injected parameters, e.g.:
// self.loginStateViewModel = parameters[0];
// self.settingsViewModel = parameters[1];
// TODO: Implement your plugin's view model here.
self.settings = parameters[0];
self.currentMaxDiff = ko.observable();
self.newMaxDiff = ko.observable();
self.someText = ko.observable();
self.showMaxDiff = function() {
self.currentMaxDiff(self.newMaxDiff());
};
self.capitalizeSomeText = function() {
var currentText = self.someText(); // Read the current value
self.someText(currentText.toUpperCase()); // Write back a modified value
};
self.onBeforeBinding = function() {
self.someText(self.settings.settings.plugins.TestPlugin.some_text());
self.newMaxDiff(self.settings.settings.plugins.TestPlugin.max_diff());
//self.showMaxDiff();
};
};
/* view model class, parameters for constructor, container to bind to
* Please see http://docs.octoprint.org/en/master/plugins/viewmodels.html#registering-custom-viewmodels for more details
* and a full list of the available options.
*/
OCTOPRINT_VIEWMODELS.push({
// This is the constructor to call for instantiating the plugin
construct: TestPluginViewModel,
// ViewModels your plugin depends on, e.g. loginStateViewModel, settingsViewModel, ...
//dependencies: [ /* "loginStateViewModel", "settingsViewModel" */ ],
// Elements to bind to, e.g. #settings_plugin_TestPlugin, #tab_plugin_TestPlugin, ...
//elements: [ /* ... */ ]
// instantiation via the parameters argument
dependencies: ["settingsViewModel"],
// Finally, this is the list of selectors for all elements we want this view model to be bound to.
elements: ["#tab_plugin_TestPlugin"]
});
});
Content of "TestPlugin_settings.jinja2"
<form class="form-horizontal">
<div class="control-group">
<!-- <label class="control-label">{{ _('Maximum Difference') }}</label> -->
<div class="controls">
<!-- <label for="inputMaxDiff"></label> -->
<!-- class="input-block-levels" -->
<p> Enter Max Diff: <input type="text" data-bind="value: settings.plugins.TestPlugin.max_diff"></p>
<p> Enter any text: <input type="text" data-bind="value: settings.plugins.TestPlugin.some_text"></p>
</div>
</div>
</form>
Content of "TestPlug_tab.jinja2"
<!--
<div class="input-append">
<input type="text" class="input-block-level" data-bind="value: max_diff">
</div>
-->
<div>
<h1>Hello!</h1>
<p> newMaxDiff: <strong data-bind="text: newMaxDiff"></strong></p>
<p> currentMaxDiff: <strong data-bind="text: currentMaxDiff"></strong></p>
<p> max_diff: <strong data-bind="text: max_diff"></strong></p>
<p> settings.plugins.TestPlugin.max_diff: <strong data-bind="text: settings.plugins.TestPlugin.max_diff"></strong></p>
<p> someText: <strong data-bind="text: someText"></strong></p>
<button class="btn btn-primary" data-bind="click: showMaxDiff">Refresh</button>
<button class="btn btn-primary" data-bind="click: capitalizeSomeText">Go Cap!</button>
</div>