I am trying to add some buttons to the GeoNetwork 3 MapViewer. Unfortunately I'm new to AngularJS, which GN3 is written in. So what I've done is editing the html-template that the 'gnMainViewer' directive is using.
ViewerDirectve.js:
module.directive('gnMainViewer', [
'gnMap',
function(gnMap) {
return {
restrict: 'A',
replace: true,
scope: true,
templateUrl: '../../catalog/components/viewer/' +
'partials/mainviewer.html',
[...]
}]);
In this template I can find the buttons that are shown in the MapView.
mainviewer.html:
<div class="wrapper" data-ng-controller="gnViewerController">
<div data-gn-alert-manager=""></div>
<div id="map" ngeo-map="map" class="map"></div>
<div gn-gfi="" map="map"></div>
<div gn-localisation-input map="map"></div>
<!--Top right buttons - Tools-->
<div class="tools tools-right" gi-btn-group gnv-close-panel data-ng-controller="toolsController">
<button class="btn btn-default" ng-model="activeTools.addLayers" type="submit"
rel="#addLayers" gi-btn gnv-tools-btn>
<span class="fa fa-plus"></span>
<span role="tooltip" data-translate="">addLayers</span>
</button>
<button class="btn btn-default" ng-model="activeTools.layers" type="submit"
rel="#layers" gi-btn gnv-tools-btn>
<span class="fa fa-tasks"></span>
<span role="tooltip" data-translate="">Layers</span>
</button>
[...]
</div>
</div>
So I've added a button let's say:
<button class="btn btn-default" ng-model="" type="submit"
rel="#" gi-btn gnv-tools-btn>
<span class="fa fa-beer"></span>
<span role="tooltip">NewButton</span>
</button>
to the template.
Then I've saved my changed and refreshed the MapView-Page on my server. But a new button will not be displayed. Also, changing the comment "Top right buttons" to something else will not make any changes to the displayed MapView-Page.
Even restarting the server won't change anything.
Could somebody explain me why AngularJS reacts like this? Any Ideas?
Turned out I had to run the page in debug mode e.g. http://localhost:8080/geonetwork/srv/ger/catalog.search?debug#/map
to force to load all AngularJS files seperately and without cache.
Related
I currently have a directive to dynamically edit a field. I have in the header of the accordion a field to edit and another field in the content of the accordion. If I click the edit button, the fields in the respective row can be edited, and this works fine. My problem is when I save or when I cancel it (when I click on the save or cancel button) immediately disappears the text field of both the header and the contents of the header. I need the text field ONLY disappear for the item in which I am going to save or cancel. When you click on the edit button, the 2 text fields should appear in both the header and the content (this works). And when clicking save or cancel, the text field in the selected element should disappear / appear.
<div ng-controller="AccordionDemoCtrl">
<uib-accordion close-others="true">
<div ng-repeat="faq in faqs">
<div class="col-sm-11" >
<div uib-accordion-group class="panel-default" is-open="faq.open">
<uib-accordion-heading >
<span ng-click="ignoreClick($event);" ><a href='' click-to-edit edit-state='faq.editState' ng-model='faq.pregunta' typeinput='textarea' >{{faq.pregunta}}</a></span> <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': faq.open, 'glyphicon-chevron-right': !faq.open}"></i>
</uib-accordion-heading>
<span click-to-edit edit-state='faq.editState' ng-model="faq.respuesta" >{{faq.respuesta}}</span>
</div>
</div>
<div class="col-sm-1" >
<button type="button" ng-click="toggleEditState($index)" class="btn btn-default">
<span class="glyphicon glyphicon glyphicon-edit"></span>
</button>
</div>
</div>
</uib-accordion>
</div>
https://plnkr.co/edit/S4OllJV64EYFNo6WIjVH?p=preview
use one-way (one-directional) binding for editState
scope: {
model: '=ngModel',
editState: '<'
},
https://plnkr.co/edit/dNehOxAIRHsRqgK9wXJx?p=preview
I believe you'll need to manage two separate booleans at the controller level so one directive doesn't overwrite the status of the other and then you have to set both booleans with your open button. I kept the master state so your glyph button will open or close both and the save/cancel should operate independently of each other.
$scope.editState = false;
$scope.editHeader = false;
$scope.editBody = false;
$scope.toggleEditState = function(index, val) {
debugger;
$scope.editState = !$scope.editState;
$scope.faqs[index].editHeader = $scope.editState;
$scope.faqs[index].editBody = $scope.editState;
}
<div ng-repeat="faq in faqs">
<div class="col-sm-11" >
<div uib-accordion-group class="panel-default" is-open="faq.open">
<uib-accordion-heading >
<span ng-click="ignoreClick($event);" ><a href='' click-to-edit edit-state='faq.editHeader' ng-model='faq.pregunta' typeinput='textarea' >{{faq.pregunta}}</a></span> <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': faq.open, 'glyphicon-chevron-right': !faq.open}"></i>
</uib-accordion-heading>
<span click-to-edit edit-state='faq.editBody' ng-model="faq.respuesta" >{{faq.respuesta}}</span>
</div>
</div>
<div class="col-sm-1" >
<button type="button" ng-click="toggleEditState($index)" class="btn btn-default">
<span class="glyphicon glyphicon glyphicon-edit"></span>
</button>
</div>
https://plnkr.co/edit/91cGWoTKyJsZQKxYapiT?p=preview
You could also communicate the master status with the directives if you wanted their input fields to open and close both.
I have a form in an Angular JS 1.4.1 prototype. I have a class on it set when it's dirty. I am trying to simulate someone "saving" the form, and therefore it's not dirty, it's "saved" so the changes are still present, but no longer dirty.
Form fragment:
<div class="override">
<tabset>
<tab heading="My Tab">
<form name="overridesForm">
<p><input ng-model="rd.isOverriden" type="checkbox"> Foobar</p>
<div class="buttons save-cancel">
<button class="btn btn-default btn-xs" ng-click="overridesForm.reset();overridesForm.$setPristine()">Cancel</button>
<button class="btn btn-primary btn-xs" ng-click="overridesForm.$setPristine()">Save with Inline</button>
<button class="btn btn-primary btn-xs" ng-click="saveData()">Save with Inline</button>
</div>
</form>
</tab>
<tab heading="Some other Tab">
blah
</tab>
</tabset>
</div>
Setting the form to pristine only works for me inline, not in a function in the controller. So this works:
<button ng-click="overridesForm.$setPristine()">Save</button>
But not this:
<button ng-click="saveData()">Save</button>
//controller:
$scope.saveData = function () {
$scope.overridesForm.$setPristine();
toastr.success('Success', 'Data was saved.');
};
I get a runtime error "no object overridesForm defined".
For reasons I have yet to figure out, it works in this codepen but not my project.
UPDATE:
After searching about accessing a form in trancluded content, I hit upon this:
<button ng-click="saveData(overridesForm)">Save with Inline</button>
and assign this in controller:
$scope.saveData = function(form) {
$scope.overridesForm = form;
$scope.overridesForm.$setPristine();
};
Not sure if this is best practice, but it works. Updated the codepen.
I'm finishing a project whose final challenge is that the system can recommend other websites based on positive vote to a site or comment on it.
The system uses a keywords field on which a search that uses easysearch, and upon which to base I want to make that recommendation system is based.
The algorithm is simple, when the user vote positive to the site the event is all your keywords and sends a easysearch that finds sites with at least one of the keywords, returns only one random site and returns the result in a nice modal message.
The template for the message is:
<template name="recommend_site">
<div class="modal fade" tabindex="-1" role="alertdialog" id="website_recommend">
<div class="modal-dialog">
<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>
<h4 class="modal-title">{{title}}</h4>
</div>
<div class="modal-body">
<h6 class="text-right">{{momentFormat createdOn}}</h6>
<p>
{{description}}
</p>
See more...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<span class="badge alert-success">{{votes.Up}}</span>
{{#if currentUser}}
<div class="btn-group" role="group" aria-label="...">
<button class="btn btn-default js-upvote">
<span class="fa fa-thumbs-o-up" aria-hidden="true"></span>
</button>
<button class="btn btn-default js-downvote">
<span class="fa fa-thumbs-o-down" aria-hidden="true"></span>
</button>
</div>
{{/if}}
<span class="badge alert-danger">{{votes.Down}}</span>
</div>
</div>
</div>
</div>
</template>
The event should make use of this search is:
Template.website_item.events({
"click .js-upvote": function (event) {
var website_id = this._id;
var keywords = this.keywords;
console.log("Up voting website with id " + website_id);
Websites.update({_id: website_id},
{$inc: {'votes.Up': 1}});
WebsitesIndex.getComponentMethods().search(keywords);
console.log(keywords);
return false;
}
});
And example of the document website is :
Websites.insert({
title:"Google",
url:"http://www.google.com",
description:"Popular search engine.",
keywords: ['google', 'popular', 'search', 'engine'],
votes:{
Up: 0,
Down: 0
},
createdOn:new Date()
});
As I said before, sarch with easysearch works great, but I can not locate that way to search keywords and taking send the result to the template. As you can see in the event I made an attempt to get the result following the documentation, but then there can not think what else I can do.
Someone can guide me ?
Update
I'm add some code in the event:
WebsitesIndex.getComponentMethods().search(keywords, { limit: 1 });
With limit: 1, i wait get one result for this search, but, i have a problem with this:
Exception in template helper: Error: Match error: Failed Match.OneOf or Match.Optional validation
at check (http://localhost:3000/packages/check.js?9c4972d3f4fe56cd455d3022e70b5195e642fc41:61:15)
at MinimongoEngine.checkSearchParam (http://localhost:3000/packages/easysearch_core.js?a1c2859756f8a6aa5fec4727e1f529e581d0f124:386:7)
at Index.search (http://localhost:3000/packages/easysearch_core.js?a1c2859756f8a6aa5fec4727e1f529e581d0f124:91:26)
at Object.getCursor (http://localhost:3000/packages/easysearch_components.js?aa6c7b1263bc20dda4038492ac0d4fd3c5104ae8:331:26)
at EachComponent.doc (http://localhost:3000/packages/easysearch_components.js?aa6c7b1263bc20dda4038492ac0d4fd3c5104ae8:956:63)
at http://localhost:3000/packages/peerlibrary_blaze-components.js?4eddb4e3f0f660190548347e680d109a51a7050f:1234:23
at http://localhost:3000/packages/blaze.js?9391df93ba5076c2cfc61ee68724eb79b65f00d9:1650:16
at http://localhost:3000/packages/peerlibrary_blaze-components.js?4eddb4e3f0f660190548347e680d109a51a7050f:1287:66
at Function.Template._withTemplateInstanceFunc (http://localhost:3000/packages/blaze.js?9391df93ba5076c2cfc61ee68724eb79b65f00d9:3671:12)
at http://localhost:3000/packages/peerlibrary_blaze-components.js?4eddb4e3f0f660190548347e680d109a51a7050f:1286:27
Well, i can see that problem is a helper problem, so, the global helper for the websiteIndex is:
Template.registerHelper('websiteIndex', () => WebsitesIndex);
But, i don't understand the problem yet.
I am using truncate.js (https://github.com/jeffchan/truncate.js) to put ellipsis into a text when it overflows. It is not working when I am following the demo right I think. Here is my code:
CSHTML File:
<div id="yammerDiv">
<div id="yammerHeader">
<img src="https://upload.wikimedia.org/wikipedia/commons/1/1f/Yammer_logo.png" alt="Yammer" height="20px;" width="50%">
</div>
<div id="yammerMessages" data-truncate-lines="3" data-toggle="modal" data-target="#myModal" style="margin-top: 25px;">
<img id="loading-gif" src="http://i559.photobucket.com/albums/ss36/madszckey01/speakker/buffering.gif">
<span id="message"></span>
<p id="sender"></p>
</div>
<div id="yammerButtons" style="display:none">
<button id="previous" type="button" class="btn btn-default btn-xs" aria-label="Left Align" onclick="onPrevious()">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
</button>
<input type="checkbox" id="myCheck" onclick="autoscroll()" data-toggle='tooltip' data-placement='bottom' data-original-title="Auto-Scroll" class='checkbox'>
<button id="next" type="button" class="btn btn-default btn-xs" aria-label="Right Align" onclick="onNext()">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
</button>
</div>
JavaScript inside the CSHTML file:
$('#yammerMessages').truncate({
lines: 3,
lineHeight: 1.5
});
I want to truncate the text in the yammerMessages div and its not working as the text just continues through the height limit of the width.
EDIT:
I have got the truncate method working but my content inside the span element 'message' reloads text often and how do I keep truncating it every time it changes?
$('#yammerMessages').truncate({
lines: 7,
lineHeight: 14
});
This truncates the text inside the div once, but when the content changes in 'message', it won't let me truncate again.
SOLVED:
Look for my answer below.
Since this library would not solve my problem, I just ended up using dotdotdot jquery library which solved my issue.
To truncate for the div, I used the dotdotdot method:
$("#text-wrapper").dotdotdot({ wrap: 'letter' });
Then when the text changes inside the div, I use the trigger method which then deletes the truncation of the element it was called on:
$("#text-wrapper").trigger("destroy");
Then I simply truncate again the new text loaded inside the div:
$("#text-wrapper").dotdotdot({ wrap: 'letter' });
For some reason the modal box works just fine but it does not load any templates I specify.
My Controller has this code;
var brnSearchModal = $modal({ scope: $scope, template: "app/rrn/searchBrn.html", contentTemplate: false, html: true, show: false });
$scope.showModal = function () {
brnSearchModal.$promise.then(brnSearchModal.show);
};
My HTML looks like this;
<button data-ng-click="showModal()" type="button" class="btn btn-info" data-animation="am-fade-and-slide-top">
BRN Lookup
</button>
And my template is in a file and looks like this;
<div class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header" ng-show="title">
<button type="button" class="close" ng-click="$hide()">×</button>
<h4 class="modal-title" ng-bind="title">Hello, World!</h4>
</div>
<div class="modal-body" ng-bind="content">Lorem ipsum dolor.</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="$hide()">Close</button>
</div>
</div>
</div>
</div>
There is no error everything seems to be working fine but the template does not load. If I debug angular-strap at one point the template is loaded but then disappears in and leaves a blank modal.
Remove ng-show="title", ng-bind="title" from the template.
Try adding the bs-modal attribute: see examples
<button data-ng-click="showModal()" type="button" class="btn btn-info" data-animation="am-fade-and-slide-top" bs-modal="brnSearchModal">
BRN Lookup
</button>
Otherwise use the data-template attribute directly without using the JS to show the modal:
<button type="button" class="btn btn-info" data-animation="am-fade-and-slide-top" data-template="app/rrn/searchBrn.html" bs-modal="modal">
BRN Lookup
</button>
I think when you put bs-modal="modal" modal is somehow pre-defined in the angular-strap library.
you should remove ng-show="title" , ng-show="content" or ng-bind="title" from the template. You should make sure that the template has no ng-show.
I know it is an old question, but in case others are looking for a solution to the same problem. I found I had to explicitly set templateUrl to falsy when setting template to an html string