Angular js - simple controller - view - modal - json

this is my simple code , i'm trying opening a modal and when opened to put data inside via controller and view, but actually still only printing "{{ i }}" inside modal
html
<body ng-controller="AppController">
<div id="modal">
<div id="modal-content"></div>
</div>
<button class="btn btn-option" onclick="modal({src:'views/layout/modals/modal.html'});">
open
</button>
</body>
modal.html :
<div ng-repeat="i in config.app_genres.genres">
{{ i }}
</div>
app.js:
.controller('AppController', function($scope,$location,$http) {
$scope.config = {};
$scope.config.app_ws = "http://localhost/And/www/";
$scope.config.app_name = "Appname";
$scope.config.app_short_description = $scope.config.app_name+" helps you go out with your rabbit";
$scope.config.app_motto = "hey ohhhhhhhhhh <i class='icon-check'></i>";
$scope.config.app_url = $location.url();
$scope.config.app_path = $location.path();
$http.get($scope.config.app_ws+'jsons/json.json').success(function(response) {
$scope.config.app_genres = response;
});
modal() js function:
function modal(_options){
/*
options = {
html:html to load,
src: false | url
}
*/
var modal = document.getElementById('modal'),
modal_content = document.getElementById('modal-content');
if(_options){
if(_options.html){
modal_content.innerHTML = _options.html;
show(modal);
}
if(_options.src){
_load(_options.src,modal_content) ;
show(modal);
}
}else{
console.log('Please set modal options');
}
}

Instead of calling the modal function directly, create a method called modal on your scope and bind it using ngClick.
Modal should really be a directive because it manipulates the DOM, but in short the reason why you aren't seeing the {{i}} resolve is because the HTML is not compiled. Angular compiles HTML it knows about, but in this example you created a new block of HTML outside of Angular.
From the controller, you could create the method to build it up, and do something like this:
// create a scope from the modal that inherits from the parent scope because it accesses properties there
var modalScope = $scope.new();
// be sure to inject the compiler service: function($scope,$location,$http,$compile)
var element = angular.element(modal_content);
$compile(element.contents())(modalScope);
Although that should work, it would be better if you considered creating a directive for the modal instead.

Related

How can I use ng-bind-html inside my directive?

I'm using templates based on my JSON. So, I can't really use my ng-bind-html like I would normally do.
Seems like the only option I have is to use my sanitized html inside an directive.
Looking for similar questions, I couldn't figure it out how to apply in my case.
Yes, I am pretty newbie into angular.
I'm currently receiving this data from my controller:
$scope.safecontainers = $sanitize($scope.containersmsg);
In my html would normally be like this:
<p ng-bind-html="containersmsg"></p>
But I don't want this, I need to use this ng-bind-html inside a directive!
Some people have talked about $compile, but I couldn't really figure it out how to apply in my case.
EDIT:
Based on comments, i'll add more code to help you guys further understand my goal.
Inside my index.html I'm declaring the controllers needed and calling my
<ng-view></ng-view>
Then, based on what I receive, i'll load one view or another:
<div ng-if='setores[0].SetorTema == "1"'>
<theme-one titulo="{{setores[0].SetorNome}}" logo="
{{setores[0].SetorLogo}}" evento="{{evento[0].EventoNome}}">
</theme-one>
// I omitted some of the parameters because they ain't relevant
</div>
My template is like this: (Just a little part of it to avoid much useless code)
<section class="target">
<div class="col-md-6 col-xs-12">
<div class="" ng-repeat="banner in title">
<div class="target-title">{{ banner.BannerLevelTitulo }}
</div>
<div class="target-desc">{{banner.BannerLevelDescricao}}</div>
</div>
</div>
<div class="col-md-6 col-xs-hidden">
<div class="target-image"><img ng-src="{{targetimage}}" alt="">
</div>
</div>
</section>
This is the controller I want my sanitized code.
hotsite.controller('containerController', function($scope, $http, $sanitize)
{
$scope.containers = [];
$scope.containersmsg = '';
$scope.safecontainers = $sanitize($scope.containersmsg);
$http.get('/Admin/rest/getContainer')
.then(function onSuccess(response) {
var data = response.data;
$scope.containers = data;
$scope.containers = response.data.filter(containers =>
containers.ContainerAtivo);
$scope.containersmsg = $scope.containers[0].ContainerDesc;
})
.catch(function onError(response) {
var data = response.data;
console.log(data);
});
});
This is a piece of my directive:
angular.module('hotsiteDirectives', [])
.directive('themeOne', function($compile) {
var ddo = {};
ddo.restrict = "AE";
ddo.transclude = true;
ddo.scope = {
titulo: '#',
...
(a lot of other scope's)
contimg: '#'
};
ddo.templateUrl = 'app/directives/theme-one.html';
return ddo;
})
And yes, I am calling the ngSanitize
var hotsite = angular.module('hotsite',['ngRoute', 'hotsiteDirectives',
'ngSanitize']);
TL;DR
This is how my code looks like inside a directive, with raw html and not rendered:
This is how it works with ng-bind-html, formatted html
If I do put this inside my view
<p ng-bind-html="containersmsg"></p>
It will be alright, all of it working like it should.
BUT, I need to call this only inside my directive, and I don't know how to do it.
So, with this context:
How can I put my sanitized html inside my directive and template?
You don't even have to trust the html to render it using ngBindHtml because the directive already does it for you. You basically need to create a parameter attribute for your directive to hold the html string, so, inside the directive's template, you use ng-bind-html="myParam".
The following snippet implements a simple demonstration of creating a directive that receives and renders an html input parameter that comes from a controller.
angular.module('app', ['ngSanitize'])
.controller('AppCtrl', function($scope) {
$scope.myHtml = '<div><b>Hello!</b> I\'m an <i>html string</i> being rendered dynamicalli by <code>ngBindHtml</code></div>';
})
.directive('myDirective', function() {
return {
template: '<hr><div ng-bind-html="html"></div><hr>',
scope: {
html: '='
}
};
});
<div ng-app="app" ng-controller="AppCtrl">
<my-directive html="myHtml"></my-directive>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular-sanitize.js"></script>

angular-ui modal is not initially hidden

I'm following this angular recipes page for adding a modal dialog to my ui. It suggests the following markup, which I've added to one of my views.
... html for my view is here ...
<button class="btn" ng-click="open()">Open Modal</button>
<div modal="showModal" close="cancel()">
<div class="modal-header">
<h4>Modal Dialog</h4>
... etc, from the recipe doc
</div>
What I want to see is my view, plus an "Open Modal" button on the bottom and nothing else. What I see instead is the button and the content of the modal already visible on the page.
The very next words in the recipe doc are:
Note that even though we don’t specify it explicitly the modal dialog
is hidden initially via the modal attribute. The controller only
handles the button click and the showModal value used by the modal
attribute.
Why is my modal mark up initially visible on the page? I think I have installed angular-ui properly... in my index.html:
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
And in my app JS:
angular.module('MonteAdmin', [
...
'ui.bootstrap',
...
])
That recipes page is likely out of date. At the time of the writing it might have been possible to pass a variable showModal to the modal directive to reveal or hide it. In your controller, you would have been able to show the modal by setting the scope variable showModal to true or false:
$scope.showModal = false;
$scope.open = function() {
$scope.showModal = true;
}
The current version does not work that way. You will have much better experience if you read the official documentation for the library at Angular UI Bootstrap
If you are using the latest version of the library, the directive is no longer modal but uib-modal. In addition, you have a bit more work to do to implement your modal.
Modal markup should be in a script tag, with a type set to text/ng-template as per the official example:
<script type="text/ng-template" id="stackedModal.html">
<div class="modal-header">
<h3 class="modal-title" id="modal-title-{{name}}">The {{name}} modal!</h3>
</div>
<div class="modal-body" id="modal-body-{{name}}">
Having multiple modals open at once is probably bad UX but it's technically possible.
</div>
</script>
To actually open the modal, your button click should trigger the following example function:
var modalInstance = $uibModal.open({
animation: $ctrl.animationsEnabled,
ariaLabelledBy: 'modal-title',
ariaDescribedBy: 'modal-body',
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
controllerAs: '$ctrl',
size: size,
appendTo: parentElem,
resolve: {
items: function () {
return $ctrl.items;
}
}
});
You must also define a controller for the modal, itself:
angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl', function ($uibModalInstance, items) {
var $ctrl = this;
$ctrl.items = items;
$ctrl.selected = {
item: $ctrl.items[0]
};
$ctrl.ok = function () {
$uibModalInstance.close($ctrl.selected.item);
};
$ctrl.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
});
All of this code is found on the official documentation for Angular UI Bootstrap

Is it possible to open a dialog or go to a new page based on the value of an object using just one button?

I'm trying to use a single "create" button that either opens a dialog or goes to a new page using ui-router, depending on the value of an object.
I'm not sure of the best way to accomplish this, I have something that seems to work, but I'm wondering if there's a better way. I'm currently using two buttons and an ng-if to hide the button I don't need at the time, but that seems messy to me.
Here's a very simple mock up of what I'm trying to do. Rather than actually opening a dialog or changing page content, I've just added alerts.
http://codepen.io/jwelker9/pen/QNPgyE?editors=1010
In short, I'm not sure how to get ui-sref and a dialog to play together on the same button.
HTML:
<div ng-controller = "lists-detail" ng-app="app">
<table class="listing">
<thead>
<tr>
<th>Item-Id:</th>
<th>Ordinal:</th>
<th>Type:</th>
<th>Content-Id:</th>
<th>
<button ng-if="!boolean"
class="button"
aria-label="Add list item"
ui-sref="site.lists">
Add New
</button>
<button ng-if="boolean"
class="button"
aria-label="Add list item"
ng-click="dialog()">
Add New
</button>
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
JS:
var app = angular.module('app', []);
app.controller('lists-detail', function ($scope) {
//actual code looks like:
//This calls an API to determine if it is correct type or not
//If boolean is true, it should open a new dialog
//if(listType == 'Episode'){
$scope.boolean = false;
//}
$scope.goToNewPage = function() {
alert("NewPage");
}
$scope.dialog = function() {
alert("Open Dialog");
}
})
If I'm understanding your question correctly, you could just call a function when the value changes and make the decision in the function like this:
https://jsfiddle.net/tma739u9/
Angular
vm.boolean = false;
vm.watchBoolean = function() {
var decision = (!vm.boolean) ? newPage() : dialog();
}
function newPage() {
$location.path('/page');
}
function dialog() {
alert('Open dialog');
}
HTML
<input
type="checkbox"
ng-model="ctrl.boolean"
ng-click="ctrl.watchBoolean()"> Click Me
In your ng-click, you can use an Angular expression like this:
ng-click="boolean==true? dialog() : gotoNewPage()"
This is a shorthand way of saying this in Javascript:
if (boolean) {
dialog();
} else {
gotoNewPage();
}

How to create a separate scope isolated from ng-repeat in Angular?

I am new to AngularJS and have some trouble understanding the concept of scope in Angular. I have read some posts on stackoverflow as well as online articles, which advise me to create a custom directive to create an isolate scope, but I am getting nowhere...
As for the project I'm working on, I am trying to make a button that when clicked, will trigger a textarea. However, because of ng-repeat, the textarea is triggered for all buttons while I click only one.
My .js file:
angular.module('myApp')
.controller('myCtrl', function ($scope, Question) {
scope.visible = false;
scope.toggle = function() {
scope.visible = !scope.visible;
};
.directive("myDirective", function () {
return {
scope: {
ngClick: '&',
ngShow: '&'
}
}
});
Here is my HTML file:
<ul>
<li ng-repeat="object in objectList">
<button type="text" myDirective ng-click="toggle()">Click</button>
<textarea myDirective ng-show="visible"></textarea>
</li>
</ul>
Angular is creating child (NOT isolated) scope when ng-repeating, try this out, when you ng-init a variable, it is only visible within that repeat div.
<div ng-repeat="i in [0,1,2,3,4,5,6,7,8,9]" ng-init="visible=false">
<button ng-click="visible=!visible">Toggle</button>
<h1 ng-show="visible">look at me!</h1>
</div>
Plunker
There is no need to use a directive. You need to use object in the foreach to refer each item in the loop.
Add visible to each object in objectList:
$scope.objectList = [
{ visible: false },
{ visible: false },
{ visible: false }
];
Then the toggle button will need to pass the object to toggle:
$scope.toggle = function (object) {
object.visible = !object.visible;
};
The ng-show will need to check object.visible and ng-click will need to pass the object:
<button type="text" ng-click="toggle(object)">Click</button>
<textarea ng-show="object.visible"></textarea>
Plunkr

How to open popup windows using angular js after click on div and pass some object to window

I want to know how to open popup window in angularjs with simple animation and background should be blur or dark
and how to pass object to that new popup window
in html
I have this type div
<div class="col-xs-7 col-md-2 rcorners2 " style="height:168px;width:126px; margin-left: 10px" ng-click="clickevent(app)">
app.js I have this:
app.controller('test',['$scope',function($scope){
$scope.clickevent=function(app){
$scope.app=app;
alert(app.name);
}
}]);
this app object content different attributes app name description...
those attribute should display in that new popup window with button
how can I do this?
Wayne suggested ngDialog which is an option but I found it to be really annoying... I simply go with the bootstrap modal or ui.bootstrap $modal... ui.bootstrap just use $modal...
you can use $modal
ref: https://angular-ui.github.io/bootstrap/
app.controller('yourController', yourController);
yourController.$inject = ['$scope', '$modal'];
function yourController($scope, $modal){...}
then start to use it.
use javascript:
assign an object to window
const pageInfo = {
name: 'myPage',
url: 'http://myPage...'
}
window.pageInfo = pageInfo;
window.open(pageInfo.url, "_blank");
then check window.opener on the next page
if (window.opener && window.opener !== null) {
console.log('has initial pageInfo !');
let pageInfo = window.opener.pageInfo;
} else {
console.log('No initial pageInfo !');
}