bootstrap modal html content knockout binding not applying popover - javascript

When I use the popover control in my modal the bindings do not work.
Here is the default content :
<form id="a" class="form-horizontal" data-bind="submit: SaveModal">
<div class="modal-body modal-content-form">
Default Content
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" class="btn btn-primary btn-modal-submit" value="Submit">
</div>
</form>
When I click my button
<button type="button" class="btn btn-info" data-toggle="modal" data-target="#modal" data-title="Information" btn-block'=""><i class="fa fa-print"></i>Quote Proposal</button>I get the new Content:
<form id="a" class="form-horizontal" data-bind="submit: SaveModal">
<div class="modal-body modal-content-form">
<div class="panel-group">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" href="#collapse001391ce-ebdb-4423-b525-40f97835fa53">Modal Controls</a>
</h4>
</div>
<div id="collapse001391ce-ebdb-4423-b525-40f97835fa53" class="panel-collapse collapse">
<div class="panel-body"><div class="row"><div class="col-sm-6">
<div class="form-group">
<label>Coverage Special</label>
<div class="input-group">
<span class="input-group-addon">$</span>
<input id="CoverageSpecial" name="CoverageSpecial" data-bind="value: CoverageSpecial" type="number" step="any" class="form-control control-font">
<span class="input-group-addon">
<a tabindex="0" data-toggle="popover" data-trigger="focus" data-placement="left" title="TextBox Numeric Help : FAQs" data-content="
This control is an html textbox of type (TextNumeric). The values
that are allowed are between a (Minimum) and a (Maximum)
integer. The (Precision) allowed will dictate the amount of
numbers after the decimal. It is (Required) and will
render a label with the (Name) value.
"><i class="fa fa-question-circle"></i></a>
</span>
</div>
<span class="help-block"></span>
</div>
</div></div></div>
<div class="panel-footer"></div>
</div>
</div>
</div></div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" class="btn btn-primary btn-modal-submit" value="Submit">
</div>
</form>
The problem is that knockout does not work if I dynamically append content. Why?

Knockout doesn't listen to changes made to the DOM. It processes the DOM tree once (after you call applyBindings) and creates event listeners and subscriptions to make sure stuff gets updated once needed. Some bindings, like the with binding, can re-apply bindings to parts of the DOM when needed.
Here's an example of a very basic way to force knockout to re-apply bindings:
We swap out parts of the DOM by using an html binding and an observable that holds the partial HTML
After each swap, we re-apply bindings to the inner part of the element that has the html binding: you cannot apply bindings to an element twice; the outer element is already bound to our initial vm
This example serves to show how knockout works, and isn't the best solution. Managing multiple binding contexts by hand can get messy. I'd suggest creating a custom binding that does this for you. Also, this solution only supports partial views that have one parent element.
var content1 = "<h1 data-bind='text: label1'>test</h1>";
var content2 = "<h2 data-bind='text: label2'>test</h2>";
var partialContent = ko.observable(null);
var reapplyBindingsToPartial = function() {
var partialVM = {
label1: "Heading 1",
label2: "Heading 2"
};
var partialElement = document.querySelector(".js-partialView").firstChild;
ko.applyBindings(partialVM, partialElement);
};
var swap = function() {
if (partialContent() === content1) {
partialContent(content2)
} else {
partialContent(content1);
}
// By now, the `html` binding was re-evaluated
reapplyBindingsToPartial();
};
var vm = {
partialContent: partialContent,
swap: swap
};
ko.applyBindings(vm);
swap();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="js-partialView" data-bind="html: partialContent"></div>
<button data-bind="click: swap">
swap
</button>

Related

How to append a div to another div

Now I have multiples PHP for loop in my project exactly the same like one below but with different PHP variables of course. I also have an add button with appends a div element. The problem is because I have many for-loop and each for-loop has an add button so when I click on one add button of a particular div it appends a new div to all.
<div class="appendOuter">
<?php
foreach($query as $data){
$id = $data['ID'];
$initialAccess = $data['Access'];
if(strlen($initialAccess) > 3){
echo '
<div class="box" >
<input type="hidden" value='.$id.' class="ID">
<textarea class="Access">'.$Access.'</textarea>
</div>';
}
}
?>
<div class="text-center">
<button class="btn btn-success btn-add" type="button" onclick="addMorediv(this)">
<span class="glyphicon glyphicon-plus"></span>
</button>
</div>
</div>
My javascript to append a new div
<script>
function addMorediv(index){
var element =$("<div class='box'><textarea class='Access'></textarea><i class='far fa-flag'></i></div>");
element.appendTo('.appendOuter');
}
</script>
Assuming that all your other HTML structure is similar to what you've demoed:
element.appendTo($(this).parent().parent());
Are you looking for something like this? Where when you click the add button, it adds a new text area under the existing textarea(s) already within that row? This is a jQuery specific answer, and doesn't require the "onclick" of button that you were using. It is also adding your content within a parent "row" div for ease of access navigating the DOM during the click event. So in your PHP for loop, you would echo out 1 of the rows in my example, using your PHP variables in the appropriate places like in your example.
$('.btn-add').on('click', function() {
var $box = $(this).parent().parent().find('.box:last');
var $element = $("<div class='box'><textarea class='Access'></textarea><i class='far fa-flag'></i></div>");
$element.appendTo($box);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="appendOuter">
<!-- Assume your PHP generated 3 ".row" div rows in for loop -->
<div class="row">
<div class="box">
<input type="hidden" value="1" class="ID">
<textarea class="Access">1</textarea>
</div>
<div class="text-center" style="padding:10px;">
<button class="btn btn-success btn-add" type="button">
<span class="glyphicon glyphicon-plus">Add +</span>
</button>
</div>
</div>
<div class="row">
<div class="box">
<input type="hidden" value="2" class="ID">
<textarea class="Access">2</textarea>
</div>
<div class="text-center" style="padding:10px;">
<button class="btn btn-success btn-add" type="button">
<span class="glyphicon glyphicon-plus">Add +</span>
</button>
</div>
</div>
<div class="row">
<div class="box">
<input type="hidden" value="3" class="ID">
<textarea class="Access">3</textarea>
</div>
<div class="text-center" style="padding:10px;">
<button class="btn btn-success btn-add" type="button">
<span class="glyphicon glyphicon-plus">Add +</span>
</button>
</div>
</div>
</div>

cancel comment in angular and change view

when i click on edit button the view is changed by ng-if how to go back by clicking cancel button
<div class="timeline-body">
<div marked="cmnt.content" class="markdown" ng-if = "editPostComment != $index " ></div>
<!--Edit comment-->
<div class="commentBox" ng-if = "editPostComment == $index " >
<textarea
rows="10" > {{cmnt.content}}</textarea>
<div class="hints">
<span class="boldtext">**Bold**</span>
<span class="italictext">_itlaics_</span>
<span class="striktext">~~strike~~</span>
<span class="codetext">'code'</span>
<span class="codetext">'''preformatted'''</span>
<span class="quotetext">>quote</span>
</div>
<div id="comment-btns">
<button class="btn btn-primary pull-left" ng-class="{'loading': commentig}" ng-disabled="commentig" ng-click="cancel()">Submit</button>
<button class="btn btn-primary pull-left cancel-edit" ng-class="{'loading': commentig}" ng-disabled="commentig" ng-click = "cancelEdit()">Cancel</button>
</div>
</div>
</div>
If your route change when clicking on edit comment, you can do it like in javascript. Try this
$scope.cancel = function(){
$window.history.back();
}
But if it only depend to the nf-if condition you can set the value of editPostComment to be different to $index as below
$scope.cancel = function(editPostComment){
editPostComment = null;
}
and then change the cancel button to
<button class="btn btn-primary pull-left" ng-class="{'loading': commentig}" ng-disabled="commentig" ng-click="cancel(editPostComment)">Submit</button>

Unable to show div from ng show

I am a new bee in angularjs and i get problem to show div through angularjs. However value are changed in subheaddiv(index) function but do not reflect in html.
Html Snipped:-
<div ng-repeat="details in feeHeadDetails">
<h4 class="panel-title">
{{details.name}}
<div ng-show="{{details.add}}">
<div ng-click="**subheaddiv($index)**" class="pull-right">
<div class="col-xs-12">
<button class="btn btn-primary"><i class="fa fa-plus"></i>Add Sub Head</button>
</div>
</div>
<div ng-show="{{details.deletable}}" class="pull-right">
<div class="col-xs-12">
<button headid="{{details.id}}" ng-click="deleteHead($event, $index)" class="btn btn-danger">Delete</button>
</div>
</div>
</div>
</h4>
Angular Script:
$scope.subheaddiv = function (index) {
$scope.feeHeadDetails[index].add = false;
$scope.feeHeadDetails[index].save = true;
console.log($scope.feeHeadDetails[index]);
};
Try to remove braces:
ng-show="details.add"
ng-show="details.deletable"
From Ng Docs
The ngShow directive shows or hides the given HTML element based on
the expression provided to the ngShow attribute.
For ng-show / ng-hide / ng-if, you can use the model expression itself instead of {{}}
<div ng-show="details.add">

Protractor + angular error - Element is not clickable at point

When trying to test a visible button on a modal window using protractor and angular, I receive the error following error:
UnknownError: unknown error: Element is not clickable at point (400, 234). Other element would receive the click: <div class="modal-footer">...</div>'.
I have tried resizing the window to a larger size in the before each statement, and have tried a scrollTo the top of the page before the click as well. Any suggestions?
Code:
it('should create a new portfolio when modal form is completed', function () {
portfolio_create_btn.first().click().then();
element(by.model('portfolios.portName')).sendKeys('Test');
element(by.css('#portfolio-modal-create-button')).click();
Tabs.filter(function (elem, index) {
return elem.getTagName('tab-heading').getText();
}).then(function (filteredElements) {
expect(filteredElements.length).toEqual(expect_tabs_len_start + 1);
});
});
Most of the HTML:
<div class="container-fluid">
<h1 class='port-title port-manager-header title custom-inline'>Portfolios</h1>
<div ng-controller="ModalCtrl" class='create-new-frame'>
<!--todo move to a partial or into $templateCache -->
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">Create New Portfolio</h3>
</div>
<form name='eventForm' method="POST">
<div class="modal-body">
<input id='create-new-portfolio-input' class='form-control' ng-model='portfolios.portName'
placeholder='Portfolio name' ng-required='true' maxlength="35" focus-me="true">
<span class="help-inline" ng-show="notUnique">Portfolio name already used</span>
<!--
Private/Group selection to be used in future versions
<div ng-init="radioModel = 'Right'; portfolios.groupSelection = false" class="btn-group">
<label class="btn btn-primary" ng-model="radioModel" ng-click='portfolios.groupSelection = true' btn-radio="'Left'">Group</label>
<label class="btn btn-primary" ng-model="radioModel" ng-click='portfolios.groupSelection = false' btn-radio="'Right'">Private</label>
</div>
-->
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok(portfolios.portName)"
ng-disabled="eventForm.$invalid || notUnique" id='portfolio-modal-create-button'>
Create
</button>
<button class="btn btn-warning" ng-click="cancel()" id='portfolio-modal-cancel-button'>Cancel</button>
</div>
</form>
</script>
<button class="btn btn-sm btn-primary create-new-frame-btn" ng-click="open('sm')">Create New</button>
</div>
<div class="title port-title custom-inline pull-right">
<!-- <span class="text-muted">
Organization // user
</span> -->
</div>
</div>
It turned out that the test before the one causing problems was opening the modal and leaving it open, and then when this test tried to open a new modal, couldn't find the button to do so because the modal was already open. I didn't realize that the very first line of the test was causing the error until I looked more closely. Problem solved.

Use Bootstrap Button Group to Swap Divs

I'm creating a login / register form for a woocommerce shop.
The default woo template shows two side by side forms, one for new customers to register, one for existing customers to login. IMHO this sucks.
I want to use a button group above a single form that swaps out the login / register forms based on the users selection, this way only one option is presented at a time. Hence, I need to swap content, and apply/remove active classes to the appropriate buttons.
I've done the following:
1.) Added a twitter bootstrap button-group like so:
<div class="col-sm-4 col-sm-offset-4">
<div class="btn-group btn-group-justified">
<div class="btn-group">
<button type="button" id="login_click" class="btn btn-default active" data-toggle="button">Login</button>
</div>
<div class="btn-group">
<button type="button" id="register_click" class="btn btn-default">Register</button>
</div>
</div>
</div>
2.) Wrapped the two forms in bootstrap classes and added IDs for simple targeting.
<div id="login_form" class="col-sm-4 col-sm-offset-4">
// login form
</div>
<div id="register_form" clas="col-sm-4 col-sm-offset-4">
//register form
</div>
I know there are built in jQuery plugins for accomplishing this. I've tried using the .active class without success. I also tried using data-toggle="button" and use the .toggle() method without success. I can't wrap my head around the appropriate jQuery, I either end up with both buttons toggled, or no buttons toggled.
Could someone guide me in the right direction?
You can just set some jQuery to hide/show the form divs:
$('#switch-forms .btn').on('click', function() {
$('#switch-forms .btn').removeClass('active');
$(this).addClass('active');
});
$('#login_click').on('click', function() {
$('#register_form').hide();
$('#login_form').show();
});
$('#register_click').on('click', function() {
$('#login_form').hide();
$('#register_form').show();
});
JS Fiddle: http://jsfiddle.net/ezrafree/HZbvA/
Also, you misspelled the class attribute on button#register_click. Updated markup is:
<div class="row">
<div class="col-sm-4 col-sm-offset-4">
<div id="switch-forms" class="btn-group btn-group-justified">
<div class="btn-group">
<button type="button" id="login_click" class="btn btn-default active">Login</button>
</div>
<div class="btn-group">
<button type="button" id="register_click" class="btn btn-default">Register</button>
</div>
</div>
</div>
</div>
<div class="row">
<div id="login_form" class="col-sm-4 col-sm-offset-4">
<p>Login Form</p>
</div>
<div id="register_form" class="col-sm-4 col-sm-offset-4">
<p>Register Form</p>
</div>
</div>
For anyone interested I made it work. Not the "bootstrap way" but it works as desired. Someone with better jQuery chops could certainly simplify this.
<script>
$(document).ready(function() {
var login_btn = $('#login_click');
var register_btn = $('#register_click');
var register_form = $('#registration_form');
var login_form = $('#login_form');
// set defaults
register_form.addClass("hidden");
login_btn.addClass("active");
// events for register button
register_btn.on("click", function(){
login_form.addClass("hidden");
login_btn.removeClass("active");
register_btn.addClass("active");
register_form.removeClass("hidden");
});
//events for login button
login_btn.on("click", function(){
register_form.addClass("hidden");
register_btn.removeClass("active");
login_btn.addClass("active");
login_form.removeClass("hidden");
});
});
</script>
Code updated
No jQuery, you could do it with bootstrap collapse.
try this
<div class="col-sm-4 col-sm-offset-4">
<div class="btn-group btn-group-justified">
<div class="btn-group">
<button type="button" id="login_click" class="btn btn-default" data-toggle="collapse" data-target=".class1">Login</button>
</div>
<div class="btn-group">
<button type="button" id="register_click" class="btn btn-default" data-toggle="collapse" data-target=".class1">Register</button>
</div>
</div>
</div>
<div class="col-sm-4 col-sm-offset-4">
<div class="class1 collapse in">123</div>
<div class="class1 collapse">321</div>
</div>
cannot comment in feed. there right way to use toggleClass
not good
$('#switch-forms .btn').on('click', function() {
$('#switch-forms .btn').removeClass('active');
$(this).addClass('active');
});
good
$('#switch-forms .btn').on('click', function() {
$('#switch-forms .btn').toggleClass('active');
});

Categories