Input value doesn't show inside bootstrap popover - angularjs

I have a directive to display a bootstrap's popover where user can update some value. The problem is that my value is not visible as an input's value (it's bind, I can edit it). Same value is visible inside the popover just next to the input.
HTML
<div custom-popover popover-html="<div><span>{{costPrice}}</span><input type='text' ng-model='costPrice' /></div>"></div>
JS
$(elem).popover({
trigger: 'manual',
html: true,
content: () => {
var content = $compile(attr.popoverHtml)(scope);
return content;
},
placement: 'bottom'
});
Demo
It's of course some piece of whole project only, but it shows the issue. Any idea of how to make this value visible inside the input?

I think I finally figured out what's the issue.
You are using jquery for pop-over as it's not a good practice to use the jquery code with angular
Here in your case you are using angular and what ng-model does is it continuously watch on the element value and if it's change it calls the digest cycle to update all the values as per the model and vice versa.
So, as you have given the angular code to jquery content function it can cause the angular to stop watching for costPrice which you can see in popover if you implement it by ui-bootstrap popover or any other angular third party popovers then you can see the effects. Here is the code for that,
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-sanitize.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="PopoverDemoCtrl">
<button style="margin:70px;" uib-popover-template="dynamicPopover.templateUrl" popover-placement="bottom-right" popover-title="{{dynamicPopover.title}}"
type="button" class="btn btn-default">Popover With Template</button>
<script type="text/ng-template" id="myPopoverTemplate.html">
<div>{{dynamicPopover.content}}</div>
<div class="form-group">
<label>Popup Title:</label>
<input type="text" ng-model="dynamicPopover.content" class="form-control">
</div>
</script>
<script>
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ngSanitize', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('PopoverDemoCtrl', function ($scope, $sce) {
$scope.dynamicPopover = {
content: 'Hello, World!',
templateUrl: 'myPopoverTemplate.html',
title: 'Title'
};
});
</script>
</div>
</body>
</html>
So as I said you gave the html with angular code to jquery to handle it and jquery cant handle the angular code so you get the error.
Hopefully this will help :)

Related

Angular validation form

I have a simple form.
<html lang="en" ng-app="MyApp">
<head>
</head>
<body ng-controller="AppCtrl">
<form name="myForm" id="myForm">
<input type="text" ng-model="field" name="myField" />
<div ng-show="myForm.myField.$error" style="color: red">
{{myForm.myField.$error}}
</div>
</form>
<script src="bower_components/angular/angular.js"></script>
<script src="controller.js"></script>
</body>
</html>
And i have angular controller
angular.module('MyApp',[])
.controller('AppCtrl', function($scope) {
$scope.myForm.myField.$error = "just to see it work";
});
Why do I get error '$scope.myForm is undefined'?
You have model, module and controller a little confused. My solutions uses Angular 1.2, although you will soon need to move to Angular 2.
Here is my reworking of your example:
<html lang="en" ng-app="MyApp">
<head>
</head>
<body ng-controller="AppCtrl as ctrl">
<form name="myForm" id="myForm">
<input type="text" ng-model="ctrl.myField" name="myField" />
<div style="color: red">
{{ctrl.myField}}
</div>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js">
</script>
<script src="controller.js"></script>
</body>
</html>
And in the controller.js:
angular.module('MyApp',[])
.controller('AppCtrl', [function() {
this.myField = "just to see it work";
}]);
In the above, I have put "myField" in the scope of the controller "AppCtrl". I have put the whole page under the control of the module 'MyApp'. You can either inject the model with "ng-bind" or use the curly bracket notation in the body of the div to bind to the "myField" model of "ctrl". I have used the latter but be aware this binding will be established after the page has been parsed.
If you load this all now, you should see "just see it work" in red under the text field, and also inside the text field. When you edit the text box, the red text will change in sync. Once you have that working, you will never want to stop learning more about Angular!
I should add that this model has a single attribute. To generalise this you will need to create a model with several properties (one for each input element), so that a JSON object is returned when the form is submitted.
You can't have dots in your variable name.
Try myFormMyFieldError instead of myForm.myField.$error.
Additional: Rather than using the attribute style, use a CSS file.

Why does this code break once "app" and the ng-controller are added?

This code is virtually verbatim from egghead.io, but it is not working at all unless I remove ="app" and remove the ng-controller attribute from the <body> element. (And of course the last <script> element gets ignored in the process—the code that would normally be in app.js.) Of course removing those bits prevents anything else from working or being added.
<!doctype html>
<html ng-app="app">
<head>
<script src="http://code.angularjs.org/angular-1.0.0.min.js"></script>
<script src="http://code.angularjs.org/angular-ui-router-1.0.0.min.js"></script>
<script>
angular.module('app', ['ui.router'])
.controller("FirstCtrl", function FirstCtrl() {
var first = this;
first.greeting = "First";
});
</script>
</head>
<body ng-controller="FirstCtrl as first">
<div>
<input type="text" ng-model="first.greeting" placeholder="First Name">
<hr>
<h1>{{ first.greeting }} World!</h1>
</div>
</body>
</html>
Here's similar code on JSFiddle. (It's only similar because JSFiddle imposes constraints that make it impossible to post identical code. It has the same problem, so I assume the differences are insignificant for tracking down the source of the bug.)
Where is the bug? Why is this not working?
With latest angular dependency it worked for me.
<!doctype html>
<html ng-app="app">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.min.js"></script>
<script>
angular.module('app', ['ui.router'])
.controller("FirstCtrl", function FirstCtrl() {
var first = this;
first.greeting = "First";
});
</script>
</head>
<body ng-controller="FirstCtrl as first">
<div>
<input type="text" ng-model="first.greeting" placeholder="First Name">
<hr>
<h1>{{ first.greeting }} World!</h1>
</div>
</body>
</html>
You are using angular ui-router but not using it the way you are supposed to be. Check the documentation here to get a clearer idea. Angular UI router loads its contents in a container containing ui-view attribute. As per documentation
AngularUI Router is a routing framework for AngularJS, which allows you to organize the parts of your interface into a state machine. Unlike the $route service in Angular core, which is organized around URL routes, UI-Router is organized around states, which may optionally have routes, as well as other behavior, attached.
You need to load different states in your ui-view and also pass values in different states in the process. You need to add dependencies for $stateProvider and $urlRouterProvider in your app config for a completely functional angular ui router implementation. This being told what you need to do is like below -
And also check out the working example in PLUNKER
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<title>AngularJS: UI-Router Quick Start</title>
<!-- Bootstrap CSS -->
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="container">
<div class="row">
<div class="span12">
<div class="well" ui-view></div>
</div>
</div>
<!-- Angular -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.js"></script>
<!-- UI-Router -->
<script src="//angular-ui.github.io/ui-router/release/angular-ui-router.js"></script>
<!-- App Script -->
<script>
var myapp = angular.module('myapp', ["ui.router"])
myapp.config(function($stateProvider, $urlRouterProvider){
// For any unmatched url, send to /route1
$urlRouterProvider.otherwise("/route1")
$stateProvider
.state('route1', {
url: "/route1",
templateUrl: "route1.html",
controller: function($scope) {
$scope.greeting = "First";
}
})
})
</script>
</body>
</html>

Angular-strap: html element is rendering as text, why?

I've just got angular-strap installed and I'm trying out some of the features. I've got a modal functioning however the content doesn't render the <br /> element, it is rendering it as text. I don't see why and the docs show that it is working correctly. As far as I can tell I'm doing everything correctly.
Can anyone spot any issue with my code? I've stripped it as bare as possible. I did previously have ngAnimate and ngSanitize included.
var app = angular.module('app', ['mgcrea.ngStrap'])
.controller('myCtrl', function($scope) {
$scope.modal = {
"title": "Title",
"content": "Hello Modal <br/> This is a multiline message!"
};
});
<html ng-app="app">
<head>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-strap/dist/angular-strap.min.js"></script>
<script src="bower_components/angular-strap/dist/angular-strap.tpl.min.js"></script>
<script src="//cdn.jsdelivr.net/angularjs/1.4.2/angular-animate.min.js" data-semver="1.4.2"></script>
<script src="//cdn.jsdelivr.net/angularjs/1.4.2/angular-sanitize.min.js" data-semver="1.4.2"></script>
<script src="app.js"></script>
</head>
<body>
Angular Strap
<div ng-controller="myCtrl">
<!-- Button to trigger a default modal with a scope as an object {title:'', content:'', etc.} -->
<button type="button" class="btn btn-lg btn-primary" data-animation="am-fade-and-scale" data-placement="center" bs-modal="modal">Click to toggle modal
<br>
<small>(using an object)</small>
</button>
</div>
</body>
</html>
Your problem may be related to the fact that Angular does not interpret HTML code when displaying any variable obtained programatically.
You should take a look at this directive: https://docs.angularjs.org/api/ng/directive/ngBindHtml, it may solve your problem!
I've got it working now.
According to the docs:
replace ng-bind with ng-bind-html, requires ngSanitize to be loaded
I set an option as per the plunkr on the docs and my code now looks like this:
var app = angular.module('app', ['ngAnimate','ngSanitize', 'mgcrea.ngStrap'])
.config(function($modalProvider) {
angular.extend($modalProvider.defaults, {
html: true
});
})
.controller('myCtrl', function($scope) {
$scope.modal = {
"title": "Title",
"content": "Hello Modal <br/> This is a multiline message!"
};
});

How to call angular controller function when ons-switch is changed?

I'm just getting into angular and onsen-ui and ran into a simple problem. I'm hoping the answer is trivial.
I have a ons-switch which I want to execute code in my controller when the switch is changed:
<ons-switch var="mark_as_favorite" onchange="toggleFavorite()"/>
This results in a toggleFavorite is not defined. This makes sense, because the scope is probably different. So how do I access the controller method from the ons-switch?
--Keith
If you are unfamiliar with AngularJS, use var attribute. var attribute dispose a Onsen UI element as a global variable.
index.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script src="components/loader.js"></script>
<link rel="stylesheet" href="components/loader.css">
<link rel="stylesheet" href="css/style.css">
<script>
ons.bootstrap();
function checkIsSwitchEnabled() {
// mySwitch is disposed as a global variable. So mySwitch is accessible from everywhere.
var isChecked = mySwitch.isChecked();
alert(isChecked);
}
</script>
</head>
<body>
<ons-navigator title="Navigator" var="myNavigator" page="page1.html">
</ons-navigator>
</body>
</html>
page1.html
<ons-page>
<div style="text-align: center">
<br/>
<br/>
<br/>
<ons-switch var='mySwitch' onchange='checkIsSwitchEnabled()'></ons-switch>
</div>
</ons-page>
this is what i did..
html
<ons-page ng-controller="yourcntrl">
<ons-switch modifier="list-item" ng-model="obj.IsSelected" ng-change="switchTrigger(obj)"></ons-switch>
</ons-page>
Js
myApp.controller('yourcntrl', function ($scope) {
ons.ready(function () {
$scope.switchTrigger= function (obj) {
alert(obj.IsSelected);
}
});
}
If you use the ngModel directive, Onsen will apply that model to the underlying checkbox and your variable will be updated automatically on change
<ons-switch ng-model="mark_as_favorite">
This is especially useful if you need to update other things on the page as they will update automatically. I use this to show and hide additional options based on the checkbox value and to apply conditional classes:
<div class="example" ng-class="{favorite: mark_as_favorite==true}">Some content</div>
You can use the ng-change attribute to execute code when the ons-switch is toggled.
Example:
<ons-page ng-controller="MyCtrl">
<ons-switch ng-model="MyCtrl.switchState" ng-change="MyCtrl.toggleSwitch(event)">/ons-switch>
</ons-page>
Now you can use event.value to access the boolean if the switch is on or off.

AngularJS - Templates : ngInclude directive

My templates contain JS, as they are called JS is not executed, you have an idea please.
For example in my JS file script.js, i have methods that apply to HTML elements in my templtes and it does not work, an idea please.
Example :
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body ng-app>
<ng-include src="'header.html'"></ng-include>
<script src="angular.js"></script>
<script src="jquery.js"></script>
<script src="script.js"></script>
</body>
</html>
header.html
<div id="header">
<div id="logo">AngularJs</div>
<div id="nav"></div>
</div>
script.js
$(document).ready(function(){
$('#nav').html('<ul><li><a href="">Link<a></li></ul>');
});
The script execute well, I feel it does not find the element div#nav.
The solution provided by Youssef can be made "more Angular", and it will not require jQuery:
<!-- template2.html -->
<script type="text/ng-template" id="template2.html">
<p ng-class="color">Content of template2.html</p>
</script>
$scope.myFunction = function() {
$scope.color = 'red';
}
http://jsfiddle.net/mrajcok/MfHa6/
In the Angular world, we try to change model properties (e.g., $scope.color) and let the view update automatically. We try to not look up elements by ID or jQuery selectors, and we try to avoid DOM manipulation in the controller -- e.g., $('#tpl2').addClass('red');
Sorry, I read wrong a part of your question, my mistake.
The DOM ready statement of jQuery will probably not work correctly. What you can do is on your ngInclude tag add a onload="FUNCTION_NAME" that contains the DOM edition you indicated inside the script.js
For more information have a look at the documentation here: http://code.angularjs.org/1.0.1/docs-1.0.1/api/ng.directive:ngInclude
--- Old Post ---
#YoussefElMontaser, you don't have to put the quotes on the ngInclude:
<ng-include src="header.html"></ng-include>
probably that is what is wrong with your script not going forward.
Let me know if that worked.
I found the solution:
http://jsfiddle.net/esjeY/
HTML
<div ng-app="">
<div ng-controller="Ctrl">
<select ng-model="template" ng-options="t.name for t in templates">
<option value="">(blank)</option>
</select>
url of the template: <tt>{{template.url}}</tt>
</div>
<div ng-include src="template.url" onload='myFunction()'></div>
</div>
JS
function Ctrl($scope) {
$scope.templates = [{
name: 'template1.html',
url: 'template1.html'
}, {
name: 'template2.html',
url: 'template2.html'
}];
$scope.template = $scope.templates[0];
$scope.myFunction = function() {
$('#tpl2').addClass('red');
}
}
#guiligan : Thanks for your help.

Resources