How to fetch JSON data and update html using BackboneJs? - javascript

I am using BackgridJs which uses Backbonejs to fill up a grid with data.
This is how my code looks like now:
<!DOCTYPE html>
<html>
<head>
<title>Terminal</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Bootstrap -->
<link href="../css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="../js/backgrid/lib/backgrid.css" />
<script src="../js/backgrid/assets/js/jquery.js"></script>
<script src="../js/backgrid/assets/js/underscore.js"></script>
<script src="../js/backgrid/assets/js/backbone.js"></script>
<script src="../js/backgrid/lib/backgrid.js"></script>
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
</head>
<body>
<h1>Hello, world!</h1>
<div class="btn-group">
<a class="btn btn-ledger dropdown-toggle" data-toggle="dropdown" href="#">
Ledger
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a tabindex="-1" href="#">With Margin</a></li>
<li><a tabindex="-1" href="#">Without Margin</a></li>
</ul>
</div>
<div class="btn-group">
<a class="btn btn-company-code dropdown-toggle" id = "company_code" data-toggle="dropdown" href="#">
Company Code
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a tabindex="-1" href="#">DHA</a></li>
<li><a tabindex="-1" href="#">HAC</a></li>
<li><a tabindex="-1" href="#">DHA</a></li>
</ul>
</div>
<div class="btn-group">
<a class="btn btn-cost-centre dropdown-toggle" data-toggle="dropdown" href="#">
Cost centre
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a tabindex="-1" href="#">ALL</a></li>
<li><a tabindex="-1" href="#">NSE-EQ</a></li>
</ul>
</div>
<div class="btn-group">
<a class="btn btn-type dropdown-toggle" data-toggle="dropdown" href="#">
Type
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a tabindex="-1" href="#">CLNT</a></li>
<li><a tabindex="-1" href="#">GENL</a></li>
<li><a tabindex="-1" href="#">MARG</a></li>
</ul>
</div>
<button type="submit" id = "submit" class="btn btn-success">
<i class="icon-circle-arrow-right icon-large"></i> Submit
</button>
<div id="example-1-result" class="backgrid-container"></div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://code.jquery.com/jquery.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="../static/js/bootstrap.min.js"></script>
<script>
var Territory = Backbone.Model.extend({});
var Territories = Backbone.Collection.extend({
model: Territory
//url: "examples/territories.json"
});
//var territories = new Territories();
var territory1 = new Territory({ name: "How Bizarre", pop: 20 });
var territory2 = new Territory({ name: "How ", pop: 21 });
var territories = new Territories([territory1,territory2]);
var columns = [{
name: "id", // The key of the model attribute
label: "ID", // The name to display in the header
editable: false, // By default every cell in a column is editable, but *ID* shouldn't be
// Defines a cell type, and ID is displayed as an integer without the ',' separating 1000s.
cell: Backgrid.IntegerCell.extend({
orderSeparator: ''
})
}, {
name: "name",
label: "Name",
// The cell type can be a reference of a Backgrid.Cell subclass, any Backgrid.Cell subclass instances like *id* above, or a string
cell: "string" // This is converted to "StringCell" and a corresponding class in the Backgrid package namespace is looked up
}, {
name: "pop",
label: "Population",
cell: "integer" // An integer cell is a number cell that displays humanized integers
}, {
name: "percentage",
label: "% of World Population",
cell: "number" // A cell type for floating point value, defaults to have a precision 2 decimal numbers
}, {
name: "date",
label: "Date",
cell: "date",
}, {
name: "url",
label: "URL",
cell: "uri" // Renders the value in an HTML anchor element
}];
// Initialize a new Grid instance
var refreshgrid = function(){
var grid = new Backgrid.Grid({
columns: columns,
collection: territories
});
// Render the grid and attach the root to your HTML document
$("#example-1-result").append(grid.render().$el);
}
// Fetch some countries from the url
//territories.fetch({reset: true});
$(".dropdown-menu li").click(function(){
$(this).closest('.btn-group').children('a').text($(this).text())
});
$('#submit').on('click', function(event) {
url = '/ledger/data'
company_code = $("#company_code").text();
// event.preventDefault(); // To prevent following the link (optional)
$.post( url, { name: "John", time: "2pm" },function(data){
ledgerData = JSON.parse(data);
refreshgrid();
});
//$.post(url,function(response){
// alert(response);
//});
});
</script>
</body>
</html>
When I get the JSON data in the Post request, I am not able to figure out how to feed it to the grid during the refreshgrid() call.
In most Backbonejs examples, the url is in the Model itself, but for me, the url keeps changing after every submit. So, how do I get the data and feed it to the grid?

By default, Backbone.js makes RESTful requests with an Accept header for application/json.
If you set a url property on a Collection, fetching the data is a simple as calling fetch
Read more about the Collection.url property here.
var CandiesCollection = Backbone.Collection.extend({url: "/candies"});
var c = new CandiesCollection;
c.fetch();
// GET /candies (Accept: application/json, text/javascript, */*; q=0.01)
Some more examples of Backbone doing magical work for you!
Backbone.js will automatically make a POST request when you save a new model (or use collection.create())
Likewise, it will automatically make a PUT request when you call model.save() on an existing model.
model.destroy() will make a DELETE request.
Aside from that, updating/refreshing is done exactly the same.

Related

How to load extensions for the Forge Viewer (without a viewerApp)

I'm trying to developp a Forge Autodesk Viewer for a webapp, this tutorial. I have an issue while trying to load extensions, indeed they never load on the viewer.
I've already developped the viewer of the tutorial, and the extensions worked correctly.
The main difference between my viewer and the tutorial's viewer is the use of a viewerApp in the tutorial while I had to use directly a GUIViewer3D (For the aggregation of several models).
I've already tried to load the viewer and the extensions in a different order, but it didn't change worked either. I assumed the code of the extension is correct, since it works in the tutorial, but I'm not sure about how I linked it to my viewer.
The code to load the viewer :
Autodesk.Viewing.Initializer(options, function onInitialized() {
// Initialisation du Viewer
var viewerDiv = document.getElementById('MyViewerDiv');
var config = {
extensions: ['DockingPanelExtension']
};
viewer = new Autodesk.Viewing.Private.GuiViewer3D(viewerDiv, config);
viewer.initialize();
});
The code of the index
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=no" />
<meta charset="utf-8">
<!-- The Viewer CSS -->
<link rel="stylesheet" href="https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/style.min.css"
type="text/css">
<!-- Developer CSS -->
<link rel="stylesheet" href="/static/style.css" type="text/css">
<!-- Common packages: jQuery, Bootstrap, jsTree -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jstree/3.3.7/jstree.min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jstree/3.3.7/themes/default/style.min.css" />
</head>
<body>
<!-- Fixed navbar by Bootstrap: https://getbootstrap.com/examples/navbar-fixed-top/ -->
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<ul class="nav navbar-nav left">
<li>
<a href="http://developer.autodesk.com" target="_blank">
<img alt="IM-Pact" src="static/img/IMPact.png"
height="20">
</a>
</li>
<li>
<button type="button" class="btn btn-default navbar-btn" onClick="callNew()">Add next model</button>
</li>
</ul>
</div>
</nav>
<!-- End of navbar -->
<div class="container-fluid fill">
<div class="row fill">
<div class="col-sm-4 fill">
<div class="panel panel-default fill">
<div class="panel-heading" data-toggle="tooltip">
Buckets & Objects
<span id="refreshBuckets" class="glyphicon glyphicon-refresh" style="cursor: pointer"></span>
<button class="btn btn-xs btn-info" style="float: right" id="showFormCreateBucket"
data-toggle="modal" data-target="#createBucketModal">
<span class="glyphicon glyphicon-folder-close"></span> New bucket
</button>
</div>
<div id="appBuckets">
tree here
</div>
</div>
</div>
<div class="col-sm-8 fill">
<div id="MyViewerDiv"></div>
</div>
</div>
</div>
<form id="uploadFile" method='post' enctype="multipart/form-data">
<input id="hiddenUploadField" type="file" name="theFile" style="visibility:hidden" />
</form>
<!-- Modal Create Bucket -->
<div class="modal fade" id="createBucketModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Cancel">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel">Create new bucket</h4>
</div>
<div class="modal-body">
<input type="text" id="newBucketKey" class="form-control"> For demonstration purposes, objects
(files) are
NOT automatically translated. After you upload, right click on
the object and select "Translate". Bucket keys must be of the form [-_.a-z0-9]{3,128}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="createNewBucket">Go ahead, create the
bucket</button>
</div>
</div>
</div>
</div>
<!-- <button id="MyNextButton" onClick="callNext()">Next!</button> -->
<!-- The Viewer JS -->
<script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/viewer3D.min.js?v=v6.6"></script>
<!-- Developer JS -->
<script src="static/js/docLoad.js"></script>
<script src="static/js/modelLoad.js"></script>
<script src="static/js/extensions/dockingpannelextension.js"></script>
<script src="static/js/viewer.js"></script>
<script src="static/js/tree.js"></script>
</body>
The code of the extension
// *******************************************
// Model Summary Extension
// *******************************************
var propsToList = [];
function addToList(item) {
if (propsToList.includes(item)) {
var index = propsToList.indexOf(item);
propsToList.splice(index, 1);
} else {
propsToList.push(item)
}
console.log(propsToList)
}
function ModelSummaryExtension(viewer, options) {
Autodesk.Viewing.Extension.call(this, viewer, options);
this.panel = null; // create the panel variable
}
ModelSummaryExtension.prototype = Object.create(Autodesk.Viewing.Extension.prototype);
ModelSummaryExtension.prototype.constructor = ModelSummaryExtension;
ModelSummaryExtension.prototype.load = function () {
if (this.viewer.toolbar) {
// Toolbar is already available, create the UI
this.createUI();
} else {
// Toolbar hasn't been created yet, wait until we get notification of its creation
this.onToolbarCreatedBinded = this.onToolbarCreated.bind(this);
this.viewer.addEventListener(Autodesk.Viewing.TOOLBAR_CREATED_EVENT, this.onToolbarCreatedBinded);
}
return true;
};
ModelSummaryExtension.prototype.onToolbarCreated = function () {
this.viewer.removeEventListener(Autodesk.Viewing.TOOLBAR_CREATED_EVENT, this.onToolbarCreatedBinded);
this.onToolbarCreatedBinded = null;
this.createUI();
};
ModelSummaryExtension.prototype.createUI = function () {
var _this = this;
// prepare to execute the button action
var modelSummaryToolbarButton = new Autodesk.Viewing.UI.Button('runModelSummaryCode');
modelSummaryToolbarButton.onClick = function (e) {
// check if the panel is created or not
if (_this.panel == null) {
_this.panel = new ModelSummaryPanel(_this.viewer, _this.viewer.container, 'modelSummaryPanel', 'Model Summary');
}
// show/hide docking panel
_this.panel.setVisible(!_this.panel.isVisible());
// if panel is NOT visible, exit the function
if (!_this.panel.isVisible()) return;
// ok, it's visible, let's get the summary!
// first, the Viewer contains all elements on the model, including
// categories (e.g. families or part definition), so we need to enumerate
// the leaf nodes, meaning actual instances of the model. The following
// getAllLeafComponents function is defined at the bottom
_this.getAllLeafComponents(function (dbIds) {
// now for leaf components, let's get some properties
// and count occurrences of each value.
// get only the properties we need for the leaf dbIds
_this.viewer.model.getBulkProperties(dbIds, propsToList, function (dbIdsProps) {
// iterate through the elements we found
dbIdsProps.forEach(function (item) {
// and iterate through each property
item.properties.forEach(function (itemProp) {
// now use the propsToList to store the count as a subarray
if (propsToList[itemProp.displayName] === undefined)
propsToList[itemProp.displayName] = {};
// now start counting: if first time finding it, set as 1, else +1
if (propsToList[itemProp.displayName][itemProp.displayValue] === undefined)
propsToList[itemProp.displayName][itemProp.displayValue] = 1;
else
propsToList[itemProp.displayName][itemProp.displayValue] += 1;
});
});
// now ready to show!
// the Viewer PropertyPanel has the .addProperty that receives the name, value
// and category, that simple! So just iterate through the list and add them
propsToList.forEach(function (propName) {
if (propsToList[propName] === undefined) return;
Object.keys(propsToList[propName]).forEach(function (propValue) {
_this.panel.addProperty(
/*name*/
propValue,
/*value*/
propsToList[propName][propValue],
/*category*/
propName);
});
});
})
})
};
// modelSummaryToolbarButton CSS class should be defined on your .css file
// you may include icons, below is a sample class:
modelSummaryToolbarButton.addClass('modelSummaryToolbarButton');
modelSummaryToolbarButton.setToolTip('Model Summary');
// SubToolbar
this.subToolbar = (this.viewer.toolbar.getControl("MyAppToolbar") ?
this.viewer.toolbar.getControl("MyAppToolbar") :
new Autodesk.Viewing.UI.ControlGroup('MyAppToolbar'));
this.subToolbar.addControl(modelSummaryToolbarButton);
this.viewer.toolbar.addControl(this.subToolbar);
};
ModelSummaryExtension.prototype.unload = function () {
this.viewer.toolbar.removeControl(this.subToolbar);
return true;
};
ModelSummaryExtension.prototype.getAllLeafComponents = function (callback) {
var cbCount = 0; // count pending callbacks
var components = []; // store the results
var tree; // the instance tree
function getLeafComponentsRec(parent) {
cbCount++;
if (tree.getChildCount(parent) != 0) {
tree.enumNodeChildren(parent, function (children) {
getLeafComponentsRec(children);
}, false);
} else {
components.push(parent);
}
if (--cbCount == 0) callback(components);
}
this.viewer.getObjectTree(function (objectTree) {
tree = objectTree;
var allLeafComponents = getLeafComponentsRec(tree.getRootId());
});
};
// *******************************************
// Model Summary Panel
// *******************************************
function ModelSummaryPanel(viewer, container, id, title, options) {
this.viewer = viewer;
Autodesk.Viewing.UI.PropertyPanel.call(this, container, id, title, options);
}
ModelSummaryPanel.prototype = Object.create(Autodesk.Viewing.UI.PropertyPanel.prototype);
ModelSummaryPanel.prototype.constructor = ModelSummaryPanel;
Autodesk.Viewing.theExtensionManager.registerExtension('ModelSummaryExtension', ModelSummaryExtension);
Thanks in advance !
In the extension JavaScript file, you're registering the extension under the name ModelSummaryExtension, but in the viewer initialization code you're passing the config object with extensions: ['DockingPanelExtension']. That's likely why the extension isn't loaded. Try initializing the GuiViewer3D class with the following config instead:
let config = {
extensions: ['ModelSummaryExtension']
};
EDIT (after the extension naming has been fixed):
When initializing the GuiViewer3D, call its start() method instead of initialize(). It will internally call initialize() (for initializing internal structures, event handlers, etc.), setUp(); (for configuring the viewer based on your config object), and finally it will call loadModel() if there's a URN or a filepath argument passed to the function.

How to filter the elements in dropdown?

I have a scenario, in that I have to filter the elements in dropdown based on input given in text box. Is it possible, so how to do that? I tried with ng-change but it is not getting.
Html code:
<input type="text" ng-model="somvar" ng-change="someFunc(somvar)" />
<div id="dropdown" class="dropdownClass">
<ul class="predtsct">
<li class="prfdwn" ng-repeat="list in countries| filter: somevar" ng-click="countryIdFunc(countriesLst.countryId)">{{list.countryName}}</li>
</ul>
</div>
From the fiddle I posted in the comments: A dropdown works no differently that an ordinary list, except that the styling is different. This example uses Bootstrap to do the dropdown, but you can find many other examples if you google them.
Working version: https://jsfiddle.net/jorgthuijls/6gvp2z9h/
This is the entire view:
<div ng-controller="MyCtrl">
city: <input type="text" ng-model="search.city">
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
Dropdown
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<!-- the 'search' bit in the filter maps to the 'search' variable on $scope -->
<li ng-repeat="user in users | filter:search:strict">{{user.name}}, {{user.city}}</li>
</ul>
</div>
</div>
The controller is also pretty small:
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.search = {};
$scope.search.city = 'new york';
$scope.users = [{
name: 'bob',
city: 'hong kong'
}, {
name: 'jack',
city: 'new york'
}, {
name: 'john',
city: 'new hampshire'
}]
}
You can use Typeahead.js it provides very flexible control of drop-down lists and filtering of it.

How would I go about figuring out what a Rails controller gets loaded twice

I am well into the development of my website and have come across a rather strange issue I can't seem to wrap my head around.
The logs for Page_1 show that the page gets loaded, then the AJAX I request gets loaded. Everything on the page looks as expected.
The logs for Page_2 (which has MUCH of the same code, though expanded functionally in various places so I can't really reuse code) show that the page loads normally, then reloads. Everything displays as expected. However if I pass a parameter to the page with a URL the parameter gets noticed on the first load, but not the second load. Data from the second load is displayed (I want data from the first load).
If it matters both pages query a Postgis database, parse some data and pass it to my coffeescript with an AJAX call.
I'm at a loss as to what areas to start investigating, as page_2 is much more complex code. Any help would be wonderful. I can post code, but suspect it's a logic issue more than just a simple coding issue.
BTW a simple query here led me to try disabling jquery, jquery-ujs, and turbolinks (which should already be disabled for these pages).
Update
This is the html output from what I've called page_2. The url I used was http://localhost:3000/map?id=12
Streissguth Gardens | Plants
<!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.6.1/html5shiv.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.3.0/respond.js" type="text/javascript"></script>
<![endif]-->
<link rel="stylesheet" media="all" href="/assets/application.self-11f9f7a32e4331868fdf90f98aee02cb97e07dd7772401c37692439c9bafad2f.css?body=1" />
<link href='http://fonts.googleapis.com/css?family=Playfair+Display' rel='stylesheet' type='text/css'>
<link href="http://fonts.googleapis.com/css?family=Merienda+One" rel="stylesheet" type="text/css">
<!-- For third-generation iPad with high-resolution Retina display: -->
<!-- Size should be 144 x 144 pixels -->
<link rel="apple-touch-icon-precomposed" type="image/png" href="/images/apple-touch-icon-144x144-precomposed.png" sizes="144x144" />
<!-- For iPhone with high-resolution Retina display: -->
<!-- Size should be 114 x 114 pixels -->
<link rel="apple-touch-icon-precomposed" type="image/png" href="/images/apple-touch-icon-114x114-precomposed.png" sizes="114x114" />
<!-- For first- and second-generation iPad: -->
<!-- Size should be 72 x 72 pixels -->
<link rel="apple-touch-icon-precomposed" type="image/png" href="/images/apple-touch-icon-72x72-precomposed.png" sizes="72x72" />
<!-- For non-Retina iPhone, iPod Touch, and Android 2.1+ devices: -->
<!-- Size should be 57 x 57 pixels -->
<link rel="apple-touch-icon-precomposed" type="image/png" href="/images/apple-touch-icon-precomposed.png" />
<!-- For all other devices -->
<!-- Size should be 32 x 32 pixels -->
<link rel="shortcut icon" type="image/x-icon" href="/assets/favicon-4f241b3fd3f72405ee0ec20d7ad9591288f5a3de1d71ec9df95330d9fd702070.ico" />
<script src="/assets/jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1"></script>
<script src="/assets/jquery_ujs.self-784a997f6726036b1993eb2217c9cb558e1cbb801c6da88105588c56f13b466a.js?body=1"></script>
<script src="/assets/turbolinks.self-c5acd7a204f5f25ce7a1d8a0e4d92e28d34c9e2df2c7371cd7af88e147e4ad82.js?body=1"></script>
<script src="/assets/bootstrap/transition.self-6ad2488465135ab731a045a8ebbe3ea2fc501aed286042496eda1664fdd07ba9.js?body=1"></script>
<script src="/assets/bootstrap/alert.self-742145c5bb847aafdadc6e339be795628f8bc25f177e851f03a8c42278eb0312.js?body=1"></script>
<script src="/assets/bootstrap/button.self-126ac9bf0e7f2d8568f8da3a00fd5f0fac6eae0946331003370161fbf8d7975e.js?body=1"></script>
<script src="/assets/bootstrap/carousel.self-e47323f363ceb3dc0bdbce05e36e709ed428e339833a41140a85cb0af24b8127.js?body=1"></script>
<script src="/assets/bootstrap/collapse.self-2eb697f62b587bb786ff940d82dd4be88cdeeaf13ca128e3da3850c5fcaec301.js?body=1"></script>
<script src="/assets/bootstrap/dropdown.self-561cca1cbaf67474e01e9536f106bad541594860a6df997004591c1c1957a147.js?body=1"></script>
<script src="/assets/bootstrap/modal.self-3e78617ade5663314b7ee0ea10375a5b34d59ffbade44939e3f2a4e4ef2019b3.js?body=1"></script>
<script src="/assets/bootstrap/tab.self-5bf7078b682f8b131332eefa46b45fa5eff2eca745fc0d03e2991450888f7c28.js?body=1"></script>
<script src="/assets/bootstrap/affix.self-6d6f1a7fc5c8aabf3547fa1b794fab6268f54bc55ad815e55873c71f52513517.js?body=1"></script>
<script src="/assets/bootstrap/scrollspy.self-969f3c5f48cdf1e439c7fa1154c13b948715f5c689f87837c0b64521d3b46ef6.js?body=1"></script>
<script src="/assets/bootstrap/tooltip.self-05afb177e08f98997ccfc84fa08a215e4b27d48d5fe4d049080675e9dffd8199.js?body=1"></script>
<script src="/assets/bootstrap/popover.self-0aa93860b59fe7393f1dd490f54b3cb994f9d6155adffce034d4e14ae361b041.js?body=1"></script>
<script src="/assets/bootstrap-sprockets.self-fbfa5ad7d9aa0afe439ec4ff3883acc4cb92b62cb67c40d674320c9aa1d4642d.js?body=1"></script>
<script src="/assets/application.self-3b8dabdc891efe46b9a144b400ad69e37d7e5876bdc39dee783419a69d7ca819.js?body=1"></script>
<script src="/assets/leaflet/leaflet-src.self-357ee0d50ed2a85182521a58430e383b89c2af8102919af7686cbc7e8af82b9b.js?body=1"></script>
<script src="/assets/leaflet.self-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.js?body=1"></script>
<script src="/assets/leaflet.markercluster/leaflet.markercluster-src.self-25776efa5512484fb238e65201dad38941babc8405ed3e77c61f0d6e92213130.js?body=1"></script>
<script src="/assets/leaflet.markercluster.self-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.js?body=1"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=MY_API_KEY"></script>
<script src="/assets/leaflet.GoogleMutant.self-e56e5f7b3a8bb83b69caeacdb557a67a3f77c2b44d76a2d825fe0184e35668a2.js?body=1"></script>
</head>
<body>
<header>
</header>
<div class="container-fluid">
<div class="row hidden-print">
<nav class="navbar navbar-default navbar-fixed-top print-hidden">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">
<img alt="SG logo" src="/assets/Leaf_logo-7d499113a70a7fdd41e8dd9b30627c600f115e8cb227156e8d0c00b5deda6d5f.png" />
</a> </div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="">Home</li>
<li class="dropdown ">
History<span class="caret"></span>
<ul class="dropdown-menu">
<li class="dropdown-header bg-success"><u>Garden</u></li>
<li>About us</li>
<li>Paths and Beds</li>
<li class="dropdown-header bg-success"><u>Neighborhood</u></li>
<li>Broadway</li>
<li>Stairs</li>
<li>Capitol Hill</li>
</ul>
</li>
<li class="dropdown active">
Plants<span class="caret"></span>
<ul class="dropdown-menu">
<li class="dropdown-header bg-success"><u>Search by</u></li>
<li>Genus</li>
<li>Common name</li>
<li>Advanced</li>
<li role="separator" class="divider"></li>
<li><a data-turbolinks="false" href="/map">Map</a></li>
</ul>
</li>
<li class="dropdown ">
Maps<span class="caret"></span>
<ul class="dropdown-menu">
<li>Plan and sections</li>
<li><a data-turbolinks="false" href="/bed">By beds</a></li>
<li><a data-turbolinks="false" href="/grid">By grid</a></li>
<li><a data-turbolinks="false" href="/location">Current location</a></li>
</ul>
</li>
<li class="dropdown ">
Community<span class="caret"></span>
<ul class="dropdown-menu">
<li>20<sup>th</sup> anniversary</li>
<li>VIP day</li>
</ul>
</li>
<li class="">Irrigation</li>
<li class="dropdown ">
Photos<span class="caret"></span>
<ul class="dropdown-menu">
<li>Winter</li>
<li>Spring</li>
<li>Summer</li>
<li>Fall</li>
<li>Snow</li>
<li>Andrea 2012</li>
</ul>
</li>
<li class="">Links</li>
<li class=""><a data-turbolinks="false" href="/directions">Directions</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
</div>
<div class="row">
<article>
<div class="col-xs-12" style="min-height: 100%;">
<div class="col-xs-12 well well-sm master_well">
<div class="page-header text-center">
<h1>Plants in the garden</h1>
</div>
<div class="col-xs-12 well well-sm ">
<div class="col-xs-12">
<p>Gears represent cluters of plants (click on them to see individual plants, or zoom in)</p>
<div id="loading">
<img src="/assets/ajax-loader-7cde6ebfd3bb8a1999f032e414003d4675bf3d42f94fd8dfa60a0573511c31e5.gif" alt="Ajax loader 7cde6ebfd3bb8a1999f032e414003d4675bf3d42f94fd8dfa60a0573511c31e5" />Loading ...
</div>
<div id="map1">
</div>
</div>
</div>
</div>
</div>
</article>
</div>
<div class="row hidden-print">
<footer class="footer">
<div class="container-fluid">
<div class="col-xs-4">
<p>© Streissguth Gardens, 2012-17</p>
</div>
<div class="col-xs-4 text-center print_hidden">
<p>Find us on
<a target="_blank" href="http://www.facebook.com/streissguthgardens">
<img alt="Facebook" height="25" src="/assets/Facebook-e2e2e1fe15151b9f4ce9290d9c6fd1cec71bc053a07f41682290ce803eaf41dd.png" />
</a> or
<a target="_blank" href="http://www.instagram.com/streissguthgardens">
<img alt="Instagram" height="25" src="/assets/Instagram-aaf78e32dbc9dd2514d65b00cbd36ab5ed5277bd1442756ebdce2edd2b79aeae.png" />
</a> at streissguthgardens</p>
</div>
<div class="col-xs-4 text-right print_hidden">
<a class="btn btn-xs btn-info" href="mailto:ben#streissguthgardens.com"><span class="glyphicon glyphicon-envelope"></span> Email us</a>
</div>
</div>
</footer>
</div>
</div>
<script src="/assets/leaflet-maps/plants.self-d66c7f3c22c956adb3ed775248bff2a6e5b020d1a3ae4c15b1122424b5e3d221.js?body=1"></script>
</body>
</html>
Here's the code from my Rails controller
def map
#pId = params[:id]
puts params.inspect
if #pId.present?
puts "-- Id present --"
#points = Point
.select('points.genus, points.species, points.cultivar, points.common_name, types.type_name')
.where(id: #pId)
.eager_load(:type)
else
puts "** Id not present **"
#points = Point
.select('points.genus, points.species, points.cultivar, points.common_name, types.type_name')
.where("types.type_name like 'Tree-%' or types.type_name like 'Shrub-%' or types.type_name like 'Perennial' or types.type_name like 'Fern' or types.type_name like 'Vine-%'")
.order(:id)
.eager_load(:type)
end
feature_collection = Point.to_feature_collection #points
#geojson = RGeo::GeoJSON.encode(feature_collection)
respond_to do |format|
format.json { render json: #geojson }
format.html
end
end
And lastly my coffeescript
$ ->
#--------------------------------------------------
# Reset div height to 60% so map will fill screen
#--------------------------------------------------
stuffToRezie = ->
h_window = $(window).height()
h_map = h_window * 0.6
$('#map1').css 'height', h_map
return
$(window).on('resize', stuffToRezie).trigger 'resize'
#--------------------------------------------------
# Build plant markers
#--------------------------------------------------
plantToMarker = (feat, latlng) ->
botName = "<i>"+feat.properties.genus
if feat.properties.species?
botName += " "+feat.properties.species+"</i>"
else
botName += "</i>"
if feat.properties.cultivar?
botName += " "+feat.properties.cultivar
botName += "<br />(#{feat.properties.common_name})<br /><a href='show?id=#{feat.id}', class='btn btn-success btn-sm btn-block active' ><span class='glyphicon glyphicon-list'></span> More info</a>"
switch feat.properties.type_id
when 12
myIcon = L.divIcon(
className: 'fIcon'
html: 'F' )
fernMarkers.addLayer L.marker(latlng, icon: myIcon).bindPopup(botName)
when 7
myIcon = L.divIcon(
className: 'pIcon'
html: 'P' )
perennialMarkers.addLayer L.marker(latlng, icon: myIcon).bindPopup(botName)
when 1
myIcon = L.divIcon(
className: 'sIcon'
html: 'B' )
shrubMarkers.addLayer L.marker(latlng, icon: myIcon).bindPopup(botName)
when 4
myIcon = L.divIcon(
className: 'sIcon'
html: 'C' )
return shrubMarkers.addLayer L.marker(latlng, icon: myIcon).bindPopup(botName)
when 2
myIcon = L.divIcon(
className: 'sIcon'
html: 'D' )
return shrubMarkers.addLayer L.marker(latlng, icon: myIcon).bindPopup(botName)
when 5
myIcon = L.divIcon(
className: 'tIcon'
html: 'B' )
return treeMarkers.addLayer L.marker(latlng, icon: myIcon).bindPopup(botName)
when 6
myIcon = L.divIcon(
className: 'tIcon'
html: 'C' )
return treeMarkers.addLayer L.marker(latlng, icon: myIcon).bindPopup(botName)
when 3
myIcon = L.divIcon(
className: 'tIcon'
html: 'D' )
return treeMarkers.addLayer L.marker(latlng, icon: myIcon).bindPopup(botName)
when 8
myIcon = L.divIcon(
className: 'vIcon'
html: 'B' )
return vineMarkers.addLayer L.marker(latlng, icon: myIcon).bindPopup(botName)
when 9
myIcon = L.divIcon(
className: 'vIcon'
html: 'D' )
return vineMarkers.addLayer L.marker(latlng, icon: myIcon).bindPopup(botName)
#--------------------------------------------------
# Build cluster sizing
#--------------------------------------------------
onEachMarker = (marker_type) ->
return iconCreateFunction: (cluster) ->
clusterCounter = cluster.getChildCount()
clusterSize = 'small'
clusterArea = 20
if clusterCounter >= 10
clusterSize = 'medium'
clusterArea = 30
if clusterCounter >= 100
clusterSize = 'large'
clusterArea = 40
L.divIcon
className: marker_type + '-cluster ' + marker_type + '-cluster-' + clusterSize
html: '<div><strong>' + clusterCounter + '</strong></div>'
iconSize: new L.point(clusterArea,clusterArea)
#--------------------------------------------------
# Variables
#--------------------------------------------------
L.Icon.Default.imagePath = '/assets'
pointStyle = {
"color": "#ff7800",
}
neCorner = L.latLng([47.635103, -122.320525])
swCorner = L.latLng([47.634083, -122.321129])
treeMarkers = L.markerClusterGroup(onEachMarker('t'))
shrubMarkers = L.markerClusterGroup(onEachMarker('s'))
perennialMarkers = L.markerClusterGroup(onEachMarker('p'))
fernMarkers = L.markerClusterGroup(onEachMarker('f'))
vineMarkers = L.markerClusterGroup(onEachMarker('v'))
#--------------------------------------------------
# Set view and load Google Maps
#--------------------------------------------------
map = L.map("map1", zoomSnap: .25)
map.fitBounds([swCorner, neCorner])
map.invalidateSize(false)
map.options.maxZoom = 22
map.options.bounceAtZoomLimits = true
googleLayer = L.gridLayer.googleMutant(type: 'roadmap').addTo(map)
map.addLayer googleLayer
#--------------------------------------------------
# Get Ajax data
#--------------------------------------------------
$.ajax
dataType: 'text'
url: window.location.pathname
send: () ->
$('#loading').show()
complete: () ->
$('#loading').hide()
success: (data) ->
L.geoJSON(JSON.parse(data),
pointToLayer: plantToMarker)
if data.length > 500
#--------------------------------------------------
# Add map control layers
#--------------------------------------------------
baseLayer = 'Base': googleLayer
overlays =
'<span class="tMarker"> - Trees</span><ul class="leaflet-list"><li>Broadleaf</li><li>Conifer</li><li>Deciduous</li><ul>': treeMarkers
'<span class="sMarker"> - Shrubs</span><ul class="leaflet-list"><li>Broadleaf</li><li>Conifer</li><li>Deciduous</li><ul>': shrubMarkers
'<span class="pMarker"> - Perennials</span>': perennialMarkers
'<span class="fMarker"> - Ferns</span>': fernMarkers
'<span class="vMarker"> - Vines</span><ul class="leaflet-list"><li>Broadleaf</li><li>Deciduous</li><ul>': vineMarkers
L.control.layers(null, overlays, {collapsed:false}).addTo map
map.addLayer treeMarkers
map.addLayer shrubMarkers
map.addLayer perennialMarkers
map.addLayer fernMarkers
map.addLayer vineMarkers
error: ->
alert "Failed to load AJAX data"
Update 2
Here's my html.erb
<% provide(:title, "Plants") %>
<% provide(:plants, "active") %>
<article>
<div class="col-xs-12" style="min-height: 100%;">
<div class="col-xs-12 well well-sm master_well">
<div class="page-header text-center">
<h1>Plants in the garden</h1>
</div>
<div class="col-xs-12 well well-sm ">
<div class="col-xs-12">
<p>Gears represent cluters of plants (click on them to see individual plants, or zoom in)</p>
<div id="loading">
<%= image_tag "ajax-loader.gif" %>Loading ...
</div>
<div id="map1">
</div>
</div>
</div>
</div>
</div>
</article>
<% content_for :header do %>
<%= javascript_include_tag "leaflet" %>
<%= javascript_include_tag "leaflet.markercluster" %>
<%= javascript_include_tag "https://maps.googleapis.com/maps/api/js?key=AIzaSyDajktKwrSpMhwXVCXZZhC1yCMYqBQCOe4" %>
<%= javascript_include_tag "leaflet.GoogleMutant" %>
<% end %>
<% content_for :javascript do %>
<%= javascript_include_tag "leaflet-maps/plants" %>
<% end %>
Here's a copy of my log also (for one load cycle)
Started GET "/map?id=12" for ::1 at 2016-12-26 12:27:19 -0800
Processing by PlantsController#map as HTML
Parameters: {"id"=>"12"}
{"id"=>"12", "controller"=>"plants", "action"=>"map"}
-- Id present --
SQL (1.0ms) SELECT points.genus, points.species, points.cultivar, points.common_name, types.type_name, "points"."id" AS t0_r0, "points"."genus" AS t0_r1, "points"."species" AS t0_r2, "points"."cultivar" AS t0_r3, "points"."common_name" AS t0_r4, "points"."type_id" AS t0_r5, "points"."created_at" AS t0_r6, "points"."updated_at" AS t0_r7, "points"."geom" AS t0_r8, "types"."id" AS t1_r0, "types"."type_name" AS t1_r1, "types"."created_at" AS t1_r2, "types"."updated_at" AS t1_r3 FROM "points" LEFT OUTER JOIN "types" ON "types"."id" = "points"."type_id" WHERE "points"."id" = $1 [["id", 12]]
Rendered plants/map.html.erb within layouts/application (50.5ms)
Category Load (0.5ms) SELECT "categories".* FROM "categories" WHERE ("categories"."id" BETWEEN 3 AND 8)
Rendered shared/_navbar.html.erb (8.5ms)
Rendered shared/_footer.html.erb (5.5ms)
Completed 200 OK in 502ms (Views: 494.2ms | ActiveRecord: 1.5ms)
Started GET "/map" for ::1 at 2016-12-26 12:27:20 -0800
Processing by PlantsController#map as TEXT
{"controller"=>"plants", "action"=>"map"}
** Id not present **
SQL (16.5ms) SELECT points.genus, points.species, points.cultivar, points.common_name, types.type_name, "points"."id" AS t0_r0, "points"."genus" AS t0_r1, "points"."species" AS t0_r2, "points"."cultivar" AS t0_r3, "points"."common_name" AS t0_r4, "points"."type_id" AS t0_r5, "points"."created_at" AS t0_r6, "points"."updated_at" AS t0_r7, "points"."geom" AS t0_r8, "types"."id" AS t1_r0, "types"."type_name" AS t1_r1, "types"."created_at" AS t1_r2, "types"."updated_at" AS t1_r3 FROM "points" LEFT OUTER JOIN "types" ON "types"."id" = "points"."type_id" WHERE (types.type_name like 'Tree-%' or types.type_name like 'Shrub-%' or types.type_name like 'Perennial' or types.type_name like 'Fern' or types.type_name like 'Vine-%') ORDER BY "points"."id" ASC
Completed 200 OK in 921ms (Views: 191.6ms | ActiveRecord: 16.5ms)
As a side note, I'm loading my JS and COFFEESCRIPT files outside of the asset pipeline because I only need them on less that 1/4 of the pages, plus I need page specific coffeescript.

AngularJS - Change view based on user preferences

I am building an email app. It consists of an option to change the default settings. When it is clicked, the following partial view is loaded.
In this view, when the Save changes button is clicked, the values chosen by the user are saved in $localStorage using ngStorage like so:
savePreferenceService.js
(function() {
'use strict';
var savePreferenceService = function ($localStorage) {
this.setPreferences = function (selectedLang, converse, selectedNumber, selectedNumberContact, reply, signature) {
$localStorage.selectedLang = selectedLang;
$localStorage.converse = converse;
$localStorage.selectedNumber = selectedNumber;
$localStorage.selectedNumberContact = selectedNumberContact;
$localStorage.reply = reply;
$localStorage.signature = signature;
console.log($localStorage.selectedLang);
console.log($localStorage.converse);
console.log($localStorage.selectedNumber);
console.log($localStorage.selectedNumberContact);
console.log($localStorage.reply);
console.log($localStorage.signature);
}
};
angular.module('iisEmail')
.service ('savePreferenceService', ['$localStorage', savePreferenceService]);
}());
I have the following questions:
1) Is there a way to store values entered by the user (e.g. selectedLang, converse, selectedNumber) in a JSON file. I have no database.
2) If the user only changes a few preferences (e.g. language preference and number of conversations per page preference), all other preferences (e.g. number of contacts per page and reply) return a value of undefined. Is there a way to return the default values for the preferences that were not changed by the user?. Here is the JSON file that contains the dropdown menu options (e.g. data.languages contains all the languages the user can choose from) and default preferences, data.userPreferences.
settings.json
{
"data": {
"languages": [
"Afrikaans",
"Albanian",
"Arabic",
"Armenian",
"Basque",
"Bengali",
"Catalan",
"Cambodian",
"Chinese (Mandarin)",
"German",
"Greek",
"Gujarati",
"Hebrew",
"Icelandic",
"Maori",
"Marathi",
"Mongolian",
"Serbian",
"Slovak",
"Slovenian",
"Spanish",
"Swahili",
"Swedish",
"Tamil",
"Tatar",
"Telugu"
],
"undoSend": [
5,
10,
20,
30
],
"conversations": [
10,
20,
30,
40,
50,
60,
70,
80,
90,
100
],
"contacts": [
20,
40,
60,
80,
100,
120,
130,
140,
180,
200
],
"userPreferences": {
"selectedLang": "Telugu",
"converse": false,
"selectedNumber": 10,
"selectedNumberContact": 20,
"reply": false,
"signature": "--"
}
}
}
3) My final goal - In the settings page, if the user selects 20 conversations per page, then the next time Inbox is clicked I want to show only 20 emails. Right now, 50 emails are being displayed like so (top-right - It says 1-50 of 277):
Does anyone have ideas regarding these questions?
UPDATE - Question 1
Looks like there is no way to store user entered data in a JSON file, so I am using localStorage to save it on the client-side.
UPDATE - Question 3
Here is a solution for question 3. I bound $scope.conversation property to conversation in the view. The value of $scope.conversation is set to the number selected by the user. This number is saved in localStorage.
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Gmail App</title>
<style>
body {
margin: 10px;
padding: 50px;
}
</style>
<link rel="stylesheet" href="Content/css/bootstrap.min.css">
<link rel="stylesheet" href="Content/css/bootstrap-theme.min.css">
<script src="Vendor/jquery-1.11.3.min.js"></script>
<script src="Vendor/bootstrap.min.js"></script>
<script src="Vendor/angular.min.js"></script>
<script src="Vendor/angular-ui-router.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.4/angular-route.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ngStorage/0.3.6/ngStorage.min.js"></script>
</head>
<body data-ng-app="iisEmail">
<div class="container" data-ng-controller="mainController">
<div class="row">
<div class="col-sm-3 col-md-2">
<div class="btn-group">
<button type="button" class="btn dropdown-toggle" data-toggle="dropdown">
Email <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li>Mail</li>
<li>Contacts</li>
<li data-ng-click="loadView('settings')">Settings</li>
</ul>
</div>
</div>
<div class="col-sm-9 col-md-10">
<!-- split button -->
<div class="btn-group">
<button type="button" class="btn btn-default">
<div class="checkbox" style="margin: 0;">
<label>
<input type="checkbox"
data-ng-click="selectAllEmail()"
data-ng-model="checkAllEmail">
</label>
</div>
</button>
</div>
<button type="button" class="btn btn-default" data-toggle="tooltip" title="Refresh">
   <span class="glyphicon glyphicon-refresh"></span>   
</button>
<!-- Single button -->
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
More <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li>Mark all as read</li>
<li class="divider"></li>
<li class="text-center"><small class="text-muted">Select messages to see more actions</small></li>
</ul>
</div>
<div class="pull-right" data-ng-controller = "settingsController">
<span class="text-muted"><b>1</b>–<b data-ng-bind = "conversation" data-ng-cloak>{{conversation}}</b> of <b>277</b></span>
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-default">
<span class="glyphicon glyphicon-chevron-left"></span>
</button>
<button type="button" class="btn btn-default">
<span class="glyphicon glyphicon-chevron-right"></span>
</button>
</div>
</div>
</div>
</div>
<hr/>
<div class="row">
<div class="col-sm-3 col-md-2">
COMPOSE
<hr/>
<ul class="nav nav-pills nav-stacked">
<li class="" data-ng-repeat="item in leftMenu">
<span class="badge pull-right"> {{item.emailCount}}</span> {{item.name}}
</li>
<!--<li>Starred</li>
<li>Important</li>
<li>Sent Mail</li>
<li>-->
</ul>
</div>
<div class="col-sm-9 col-md-10">
<!-- Nav tabs -->
<ul class="nav nav-tabs">
<li class="active"><a href="#home" data-toggle="tab"><span class="glyphicon glyphicon-inbox">
</span>Primary</a></li>
<li><a href="#profile" data-toggle="tab"><span class="glyphicon glyphicon-user"></span>
Social</a></li>
<li><a href="#messages" data-toggle="tab"><span class="glyphicon glyphicon-tags"></span>
Promotions</a></li>
<li><a href="#settings" data-toggle="tab"><span class="glyphicon glyphicon-plus no-margin">
</span></a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div ui-view></div>
</div>
</div>
</div>
</div>
<script src="app/main.js"></script>
<!--Services-->
<script src="app/services/commonApiService.js"></script>
<script src="app/services/savePreferenceService.js"></script>
<script src="app/services/fetchDataService.js"></script>
<script src="app/controllers/mainController.js"></script>
<script src="app/controllers/settingsController.js"></script>
<script src="app/controllers/emailViewController.js"></script>
</body>
</html>
savePreferenceService.js
(function() {
'use strict';
var savePreferenceService = function ($localStorage) {
this.setPreferences = function (selectedLang, converse, selectedNumber, selectedNumberContact, reply, signature) {
$localStorage.selectedLang = selectedLang;
$localStorage.converse = converse;
$localStorage.selectedNumber = selectedNumber;
$localStorage.selectedNumberContact = selectedNumberContact;
$localStorage.reply = reply;
$localStorage.signature = signature;
};
};
angular.module('iisEmail')
.service ('savePreferenceService', ['$localStorage', savePreferenceService]);
}());
settingsController.js
(function() {
'use strict';
var settingController = function (fetchDataService, $scope, savePreferenceService, $localStorage) {
$scope.url = 'app/mock/settings.json';
$scope.save = {};
fetchDataService.getContent($scope.url)
.then(function(response){
$scope.contacts = response.data.contacts;
$scope.languages = response.data.languages;
$scope.conversations = response.data.conversations;
$scope.undoSend = response.data.undoSend;
$scope.save = response.data.userPreferences;
});
$scope.setPreference = function () {
savePreferenceService.setPreferences($scope.save.selectedLang, $scope.save.converse, $scope.save.selectedNumber, $scope.save.selectedNumberContact, $scope.save.reply, $scope.save.signature);
};
$scope.conversation = $localStorage.selectedNumber;
};
angular.module('iisEmail')
.controller ('settingsController',
['fetchDataService', '$scope', 'savePreferenceService', '$localStorage', settingController]);
}());

Changing bootstrap dropdown button's text using an angular.js directive

I am working on an application and before getting too deep I wanted to do a test. I have a button created using Bootstrap. I have the Bootstrap angular directives installed. I wanted to change the text of the button based upon the selection the user makes on that button. Here is my code:
the Index.html file:
<!doctype html>
<html ng-app="SchedgMeApp">
<head>
<!--<script src="js/angular.min.js"></script>-->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
<script src="js/ui-bootstrap-custom-tpls-0.12.0.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="js/app.js"></script>
<link href="css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="DropdownCtrl">
<!-- Single button -->
<div class="btn-group" dropdown is-open="status.isopen">
<button type="button" class="btn btn-primary dropdown-toggle" dropdown-toggle ng-disabled="disabled">
<span class="selection">{{ selectedAction.name }}</selection> <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li ng-repeat="action in actions">
<a ng-click="setAction(action)">{{ action.name }}</a>
</li>
</ul>
</div>
</div>
</body>
</html>
The app.js file:
var app = angular.module('SchedgMeApp',['ui.bootstrap']);
angular.module('SchedgMeApp').controller('DropdownCtrl', function($scope, $log){
$scope.status = {
isopen: false
};
$scope.toggled = function(open) {
$log.log('Dropdown is now: ', open);
};
$scope.toggleDropdown = function($event) {
$event.preventDefault();
$event.stopProagation();
$scope.status.isopen = !$scope.status.isopen;
};
$scope.actions = [
{id: 'calbert', name: 'Chris Albert'},
{id: 'mmahony', name: 'Mike Mahony'},
{id: 'ctfletcher', name: 'CT Fletcher'},
{id: 'rjohnson', name: 'Rob Johnson'}
];
$scope.setAction = function(action) {
$scope.selectedAction = action;
};
});
This works, but the code to change the text on the button is in the controller and I would prefer it in a directive because I would like to be able to populate the data for every dropdown button in my site this way and have every dropdown button in my site respond in the same manner. So here are my questions:
How do I do this through an angular directive?
How can I set a default value on initial load? <-- solved...see comment
How can I make this so that I have data for all the buttons in my JS, but can pick which data to use on a particular button? I assume a model? <--solved...see comment

Categories