Knockout : Unable to process binding on observable & issue with initialization - javascript

I have googled around, and tried to fix this as good as i can with examples i have found around, but alas... no success.
Mission :
Modal is opened and displaying checkbox for selecting an already existing user
If clicked -> Dropdown visible with available persons to select from
Source of dropdown (select) works as it should..
When person is selected from dropdown, a api-call (not implemented yet) will return an object to fill newOrExistingPlayer observable, and displaying it's data in fields..
If no person selected from dropdown, it's a new registration without pre-selecting a person.
Error :
knockout-3.4.0.debug.js:3326 Uncaught ReferenceError: Unable to process binding "with: function (){return newOrExistingPlayer }"
Message: Unable to process binding "value: function (){return selectedPersonId }"
Message: selectedPersonId is not defined
Problem :
Before a person is selected, newOrExistingPlayer is "undefined". Therefore i made a "teamPlayerDefault" js-object with the data similar to what should be returned from the api call (not implemented yet).
This is for initializing..
I don't think i'm handling empty observables the correct way. Should they be initialized in some way to avoid this ?
JSFiddle Link :
Click here...
Code :
$(document).ready(function() {
var NewTeamPlayerViewModel = function() {
var teamPlayerDefault = {
Id: 0,
ExistingPersonId: 0,
Email: "",
Email2: "",
FirstName: "",
LastName: "",
Address: "",
PostalCode: "",
PostalCity: "",
Phone: "",
Phone2: "",
BirthdayString: "",
ShirtNo: 0,
TeamIdString: getQueryVariable("teamId")
};
var self = this;
self.existingPersonChecked = ko.observable(false);
self.existingPersons = ko.observableArray();
self.selectedPersonId = ko.observable(null);
self.selectedPersonId.subscribe(function(selPersonId) {
// Handle a change here, e.g. update something on the server with Ajax.
console.log('Valgt personid ' + selPersonId);
});
self.newOrExistingPlayer = ko.observable(teamPlayerDefault);
self.setExistingPlayer = function(personId) {
// TODO : GET EXISTING PLAYER
self.newOrExistingPlayer(null);
console.log(self.newOrExistingPlayer());
}
self.toggleExistingPersonChecked = function() {
self.existingPersonChecked(!self.existingPersonChecked);
}
// TODO UGLE : Ikke hent alle personer, men ekskluder de som allerede er spillere på laget!!!
self.initializeFromServer = function() {
//var teamId = getQueryVariable("teamId");
var url = 'api/User/GetAllPersons';
$.getJSON(url)
.done(function(data) {
newPlayerModel.existingPersons(data);
//console.table(data);
});
}
}
var newPlayerModel = new NewTeamPlayerViewModel();
newPlayerModel.initializeFromServer();
ko.applyBindings(newPlayerModel, document.getElementById("ko-player"));
console.log("Heisann!" + newPlayerModel.newOrExistingPlayer());
});
<div id="ko-player">
<div class="modal fade" data-bind="with: newOrExistingPlayer" id="full-modal-player" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="z-index: 999999999999">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 id="myModalLabel">Ny spiller</h4>
</div>
<div class="modal-body" style="height: 100% !important; max-width: 100%; height:800px">
<div class="row">
<div class="col-sm-12">
<div class="col-sm-6">
<div class="checkbox">
<label class="checkbox-label">Velg eksisterende person?</label>
<input type="checkbox" data-bind="checked: $parent.existingPersonChecked, click: $parent.toggleExistingPersonChecked" />
</div>
</div>
<div class="col-sm-6" style="display: none" data-bind="visible: $parent.existingPersonChecked">
<div class="form-group">
<label>Velg person:</label>
<select data-bind="options: $parent.existingPersons, value: selectedPersonId, optionsCaption: 'Velg en person'"></select>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Lukk</button>
<div class="clear:both; height:1px"> </div>
</div>
</div>
</div>
</div>
</div>

You likely have figured this out by now but I was able to get it binding with -
<select data-bind="value: $parent.selectedPersonId"></select>
Just to expand on why this is, you are binding 'with' newOrExistingPlayer and need to step up a level to access where you defined the selectedPersonId

Related

show particular data in pop up modal in vue.js

this is regarding Vue.js question
i'm trying to open bootstrap model form inside the Vue template
i use two vue template components,
this sub component call inside this competence and pass data from this to sub component
this component use for show particular (load one by one products) model data
so i need to show one by one products data on the model form (when product 1 show name 'Abc') like this
but i cant do this.. all implementation are done and working fine
but cant show the particular data on the model form
show it only first loop value (i have 3 products all load in the table,but when click edit button first product show correctly,but click 2nd product show first product data)
but when i call console.log function and view when open the model show particular data in the console, but not showing its on the model form
why it that
i put my code segment in the below
example-component
<tbody >
<tr div v-for="invoices in invoice">
<th class="invoice_name ">{{invoices.p_name}}</th>
<td class="unit">
<sub-com :pID=invoices.p_id :invoice=invoices :invoiceID=invoice_id></sub-com>
</td>
</tr>
</tbody>
sub-com
<template>
<div>
<div class="form-group">
Refund
</div>
<div class="col-md-6">
<div class="modal fade" id="refundModel" tabindex="-1" role="dialog" aria-labelledby="addNewLabel"
aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form>
<div class="modal-body">
<div class="form-group">
<input v-model="form.name" type="text" name="name" placeholder="Name" class="form-control">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
this is sub.vue script segment
<script>
export default{
data(){
return{
form: {
name:''
}
}
},
props: {
pID: String,
invoiceID:String,
invoice:{},
}
methods: {
refundMethod(invoices){
this.form.name = invoices.p_name;
console.log(invoices.p_name);
$('#refundModel').modal('show');
}
}
There are a couple of issues that might clear things up.
First you need to add a key to your template v-for loop:
<tr v-for="invoices in invoice" :key="invoices.p_id">
Second you are using jquery to trigger the modal which could work but you will have to generate unique ids for each div:
<div :id="'refundModel_'+pID">
A more Vue way to do this is to use the bootstrap data-show attribute and link it to a Boolean modal property in your data:
<div :data-show="modal" :id="'refundModel_'+pID">
export default {
data(){
return{
modal : false,
form: {
name:''
}
}
},
props: {
pID: String,
invoiceID: String,
invoice: Object,
}
methods: {
refundMethod(invoices){
this.form.name = invoices.p_name;
console.log(invoices.p_name);
this.toggleModal()
}
toggleModal () {
this.modal = !this.modal
}
}
}

Is it possible to add dynamic value to #Html.ActionLink param

I have a method in my MVC controller, that when invoked downloads a document.
I have a bootstrap Modal, where the href resides which points to this method.
#Html.ActionLink("Download", "Download", new { applicantId = 1, templateId = 1 })
The applicantId and templateId for the minute are hardcoded, but these values are passed to the Modal via jquery as text values.
Is it possible to get a HTML id dynamically and add it to the #Html.ActionLink?
Modal:
<div id="template1">
<div class="modal fade" id="myModal1" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<h3 id="app" style="display:none"></h3>
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">Letter Template Logo</h4>
</div>
<div class="modal-body">
<img style="background-size:cover;" src="~/Content/images/image.png" alt="" />
</div>
<div class="modal-footer">
ActionLink("Download", "Download", new { applicantId = 1, templateId = 1 })
</div>
</div>
</div>
</div>
</div>
I have created .NetFiddle. It works here
You can change Html.ActionLink() method parameters with .replace() method and you can implement like following.
//html
Parameter 1:<input id="param1" />
Parameter 2:<input id="param2" />
<div class="modal-footer">
#Html.ActionLink("Download", "Example", new { applicantId = 1, templateId = 1 })
</div>
<button id="yourbutton">Change Action Link</button>
//jquery
<script type="text/javascript">
$("#yourbutton").on("click",function(){
var param1 = $("#param1").val();
var param2 = $("#param2").val();
console.log(param1);
console.log(param2);
var link = '#Html.ActionLink("Download", "Example",
new { applicantId = "_applicantId_", templateId = "_templateId_"})';
if(param1 == "" || param2 == "")
{
alert("please fill all parameter inputs")
}
else
{
link = link.replace('_applicantId_', param1);
link = link.replace('_templateId_', param2);
$(".modal-footer").html(link)
alert("I have changed ActionLink. Please click the download link")
}
})
</script>
#Html.ActionLink("Pond", "Pond", "Home", htmlAttributes: new {
#class="classNameYouWantToAdd" })
or
#Html.ActionLink("Pond", "Pond", "Home", new {
#class="classNameYouWantToAdd" })
if you want to do it from JQuery then you can either target the li tag that contains the link or Add a class name to the your action link like above and then update the class of the object as your normally would.
$('.TargetedClassNameOfActionLink').addClass('addDifferentClass').removeClass('removeSomeOtherClass')
$('#liTagId').find('.ClassNameOfActionLink').addClass('addDifferentClass').removeClass('removeSomeOtherClass')
or
$('#tabPond').addClass("greenTab");

Knockout Component View Not Updating When Its ViewModel Observable Changes

I have a component setup to use AMD to get the html template and viewmodel code. Everything works fine. The component loads when it is supposed to and behaves fine with the params passed to it. The problem is I defined an observable in the viewModel whose value shows up in the template view, but when the observable's value changes the text on the view does NOT change. Can anyone explain what is going on here? The text I am trying to bind to is modalTitle. When the modal loads its title is 'TEMP' but if I go to the console and type 'window.modalTitle()' I get 'CREATE REPORT SCHEDULE'. It's like the view is getting the first value of the observable and then ignoring it after that. Is there anyway I can force it to look for updates?
ViewModel: (schedules.component.js)
define(['knockout'], function (ko) {
console.log('schedules hit');
loadCss('schedules');
function SchedulesViewModel(params) {
this.scheduledItems = params.scheduledItems;
this.itemName = params.itemName;
this.modalTitle = ko.observable("TEMP");
window.modalTitle = this.modalTitle;
}
SchedulesViewModel.prototype.initiateAddScheduledItem = function () {
this.modalTitle("CREATE " + this.itemName + " SCHEDULE");
$('#schedulesModal').modal('show');
};
SchedulesViewModel.prototype.removeSelectedScheduledItem = function () {
this.chosenValue('dislike');
};
window.ReportsApp.SchedulesViewModel = SchedulesViewModel;
return SchedulesViewModel;
});
View Template
<div id="schedulesModal" class="modal fade lcmsModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<!--<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>-->
<img src="/Content/images/modalASLogo.png" style="float: right;" />
<h4 class="modal-title" data-bind="text: modalTitle()">Test Title</h4>
</div>
<div class="modal-body">
<p>One fine body ...</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">CANCEL</button>
<button type="button" class="btn btn-primary">SAVE</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- /Bootstrap Modal -->
It does not get changed because this.itemName has not been defined as an observable. it is better to define a computed observable which will automatically update whenever any observables change.
Instead of using prototype to add methods, you can use knockout function which foes it for you.
Example :https://jsfiddle.net/kyr6w2x3/34/
function SchedulesViewModel(params) {
var self = this ;
self.scheduledItems = ko.observable(params.scheduledItems);
self.itemName = ko.observable(params.itemName);
self.modalTitle = ko.observable("TEMP");
self.chosenValue= ko.observable();
self.modalTitle = ko.computed(function() {
return "CREATE " + self.itemName() + " SCHEDULE" ;
}, self);
// you can change below to show your modal whenever you want
$('#schedulesModal').modal('show');
self.removeSelectedScheduledItem = function (){
self.chosenValue('dislike');
}
}
ko.applyBindings(new SchedulesViewModel({scheduledItems:"scheduledItems" ,itemName : "itemName" }));
Update : yes you can have multiple view models or better to say nested view models. Look at the new example and see how you can communicate between your models.https://jsfiddle.net/kyr6w2x3/35/

Meteor: how to retrieve "{{this}}-value" with a template event

Note: Whole code can be found here:
https://github.com/Julian-Th/crowducate-platform/tree/feature/courseEditRights
The issue: I can't retrieve the {{this}} value with an event. Console.log() is printing 0.
My HTML:
<!-- Modal to control who can collaborate on a course-->
<template name="modalAddCollaborators">
<div id="modalAddCollaborators" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Manage Your Collaborators</h4>
</div>
<div class="modal-body">
<form class="form" role="form">
<ul class="list-group">
{{#each addedCollaborators}}
{{#each canEditCourse}}
<li class="list-group-item js-listed-collaborator">{{this}}<a title="Remove Collaborator" id="remove-collaborator" class="btn btn-danger pull-right" href="#"><i class="fa fa-trash"></i></a></li>
{{/each}}
{{/each}}
</ul>
<div class="form-group">
<input class="form-control typeahead" type="text" id="collaboratorName" placeholder="add a collaborator ..." data-source="courses" autocomplete="off" spellcheck="off">
<button type="button" id="js-addCollaborator" class="btn btn-success">Add</button>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</template>
My JS:
Template.modalAddCollaborators.rendered = function() {
// initializes all typeahead instances
Meteor.typeahead.inject();
};
Template.modalAddCollaborators.courses = function(){
return Courses.find().fetch().map(function(it){ return it.author; });
//return users.find().fetch().map(function(it){ return it.username; });
};
Template.modalAddCollaborators.helpers({
'addedCollaborators': function () {
return Courses.find().fetch();
}
});
Template.modalAddCollaborators.events({
'click #js-addCollaborator' : function (event) {
var collaboratorName = $('#collaboratorName').val(); //
Courses.update(
{_id: this._id},
{$addToSet: {canEditCourse: collaboratorName}}
);
$('#collaboratorName').val("");
},
'click #remove-collaborator': function (event) {
var listedCollaborator = $('.js-listed-collaborator').val();
console.log(listedCollaborator);
Courses.update(
{_id: this._id },
{$pull: {canEditCourse: listedCollaborator}}
);
}
});
My MongoDB JSON:
{
"_id" : "j7A3tFdFBn5ECQGwe",
"title" : "Beatles",
"coverImageId" : "RERiadyMx8j8C9QQi",
"author" : "John",
"keywords" : [
"Paul"
],
"published" : "true",
"about" : "Testing the Course",
"canEditCourse" : [
"uo8SMdNroPGnxMoRg",
"FLhFJEczF4ak7CxqN",
"lkahdakjshdal",
"asödjaöslkdjalsöSA"
],
"createdById" : "uo8SMdNroPGnxMoRg",
"dateCreated" : ISODate("2015-12-28T16:30:34.714Z")
}
As seen in the JS-File, my final goal is to delete the clicked user from an array.
To get the text of the li item in the child link click event, combine the use of .parent() and .text() (since you can't use .val() on list items):
'click #remove-collaborator': function (event) {
console.log(event.target);
var listedCollaborator = $(event.currentTarget).parent().text();
console.log(listedCollaborator);
console.log(JSON.stringify(Template.parentData(0)));
Courses.update(
{
_id: Template.parentData(0)._id, /* or _id: Template.currentData()._id, */
canEditCourse: listedCollaborator
},
{ $pull: { canEditCourse: listedCollaborator } }
);
}
Notice you can use the current DOM element within the event bubbling phase through event.currentTarget to reference the element that kicked off the event. Since the element is the anchor tag, you get the li item as
its .parent(), and subsequently get its value with .text().
As for the update, use Template.parentData() to get the parent _id. Specify a parameter of 0 in the method which denotes the current data context level to look.
For example, Template.parentData(0) is equivalent to Template.currentData(). Template.parentData(2) is equivalent to {{../..}} in a template.
Since you've attached your event handler to the modalAddCollaborators template this will be the data context of that template which is nothing.
Just setup a nested template at the level you want to catch the event.
Furthermore with this pattern you can identify the _id of the collaborator directly, it will be this. The course _id however comes from the context of the parent template. (I'm not sure whether the course level data context is 1 or 2 levels higher however).
html:
{{#each canEditCourse}}
{{> nestedTemplate }}
{{/each}}
<template name="nestedTemplate">
<li class="list-group-item js-listed-collaborator">
{{this}}<a title="Remove Collaborator" id="remove-collaborator" class="btn btn-danger pull-right" href="#"><i class="fa fa-trash"></i></a>
</li>
</template>
js:
Template.nestedTemplate.events({
'click #remove-collaborator': function (event) {
Courses.update({_id: Template.parentData()._id },{$pull: {canEditCourse: this}});
}
});

I want to show ModalDialogbox to clients when Clients click on resetlink

I am doing resetpassword system in Meteor,I want to show ModalDialogbox to clients when Clients click on resetlink but couldn't do it.
account.html
this is my ResetPasswordform and Modal
<template name="ResetPassword">
{{#if resetPassword}}
<div class="modal fade" id="myModal-9" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<span class="f-s-20 text-blue">ŞİFRE DEĞİŞTİRME EKRANI </span>
</div>
<div class="modal-body">
<form action="/reset-password" id="resetPasswordForm" method="post">
<div class="form-group">
<input id="resetPasswordPassword" type="password" name="newpassword" class="form-control width-250 m-auto" placeholder="Yeni Şifrenizi Girin">
</div>
<div class="form-group">
<input id="resetPasswordPasswordConfirm" type="password" name="newpasswordconfirm" class="form-control width-250 m-auto" placeholder="Yeni şifre tekrarla">
</div>
<div class="form-group">
<button type="button" id="resetpasswordbtn" class="btn btn-theme width-250" value="Reset">Yenile</button>
</div>
</form>
</div>
</div>
</div>
</div>
{{/if}}
</template>
account.js
if (Accounts._resetPasswordToken) {
Session.set('resetPassword', Accounts._resetPasswordToken);
}
Accounts.onResetPasswordLink(function (token, done) {
Session.set('resetPassword', token); meteo
done(); // Assigning to variable
$t.find('#myModal-9').modal('show');
});
Template.ResetPassword.helpers({
resetPassword: function () {
return Session.get('resetPassword');
}
});
I use bootbox to display bootstrap-style modals in Meteor, using Meteor templates (so that the modals are reactive). If you
meteor add mizzao:bootboxjs
Then the following function will suffice to display a modal:
function displayModal(template, data, options) {
// minimum options to get message to show
options = options || { message: " " };
var dialog = bootbox.dialog(options);
// Take out the default body that bootbox rendered
dialog.find(".bootbox-body").remove();
// Insert a Meteor template
// Since bootbox/bootstrap uses jQuery, this should clean up itself upon removal
Blaze.renderWithData(template, data, dialog.find(".modal-body")[0]);
return dialog;
}
You'll find that the default bootbox modals are also useful for non-reactive messages.

Categories