So I am working with Knockout inside Magento 2.3.4, and I am setting a custom observable value on initialize, and then I am trying to access that observable and change the value inside a function. Every time I try, I keep getting "it is not a function", and it won't let me either retrieve and read the current observable value, or set a new one. When I try to run .isObservable() on it it comes up as false. I have looked through various examples of how to do it and tried all of them and none of them work. Currently my knockout JS form looks like this:
define([
'jquery',
'uiComponent',
'ko'
], function($, Component, ko) {
'use strict';
return Component.extend({
defaults: {
template: 'Shmoop_Cms/career-form'
},
progressText: ko.observable(false),
initialize: function() {
var self = this;
this._super();
this.progressText('1 of 15 questions completed');
return this;
},
showNext: function() {
let dataIndex = parseInt($('.quiz-card.show').attr('data-index')) + 1;
alert(ko.isObservable(this.progressText));
alert(this.progressText());
this.progressText(dataIndex + ' of 15 questions completed');
}
});
});
I am able to set the progressText value initially inside that initialize function without issue, and it recognizes there that it is an observable. Why does it say it's not an observable inside by "showNext" function?
FYI I have also tried adding "var self = this" inside my function, I have also tried "self.progressText()" instead of "this.progressText()", nothing worked.
Please help.
Edited: By the way, my template looks like this:
<div class="career-quiz-wrapper">
<!-- ko if: quizQuestions -->
<form class="career-quiz-form" data-bind="foreach: quizQuestions">
<div class="quiz-card" data-bind="attr: {'data-question-uuid': uuid, 'data-index': index }, css: index == 0 ? 'show' : 'hide'">
<h2 class="display-heading title">How important is it to you to...</h2>
<div class="lead main-text" data-bind="html: question"></div>
<div class="choices">
<div class="row-bar">
<input type="range" data-anchor="range" class="custom-range" min="0" max="100" value="50" autocomplete="off" data-bind="event: { change: $parent.adjustRangeSlider }">
</div>
<div class="row-options">
<div class="option-section" data-bind="foreach: choiceUUIDs">
<div class="choice-option-button">
<a class="option-button" data-bind="click: $parents[1].choiceClicked, attr: { 'data-choice-uuid': UUID, 'data-range-value': rangeValue, title: textOption }, text: textOption, css: (i && i == 2) ? 'selected' : ''"></a>
</div>
</div>
<div class="mobile-bar">
<input type="range" data-anchor="range" class="custom-range" min="0" max="100" value="50" autocomplete="off" data-bind="event: { change: $parent.adjustRangeSlider }">
</div>
</div>
</div>
<div class="choice-buttons">
<div class="choice-button">
<a data-bind="click: $parent.showCareers" class="blue-link" title="Show Careers">Show Careers</a>
</div>
<!-- ko if: index == ($parent.quizQuestions().length - 1) -->
<div class="choice-button">
<a class="pink-button results-button" data-bind="click: $parent.getResults" title="Get Results">Get Results <i class="fa fa-cog fa-spin d-none"></i></a>
</div>
<!-- /ko -->
<!-- ko ifnot: index == ($parent.quizQuestions().length - 1) -->
<div class="choice-button">
<a class="pink-button next-question" data-bind="click: $parent.showNext" title="Next Question">Next Question</a>
</div>
<!-- /ko -->
</div>
<div class="quiz-progress">
<p class="progress-text" data-bind="text: $parent.progressText"></p>
</div>
</div>
</form>
<!-- /ko -->
<!-- ko ifnot: quizQuestions -->
<div class="error-message">
<p>
Sorry, something went wrong. I guess you'll have to figure out what to do on your own..
</p>
</div>
<!-- /ko -->
I have had issues with javascript object literals before and would probably approach it like this. Not sure if this works as I haven't tested it.