Related
I have a small Wordpress site that I build statically using Gatsby, using the excellent gatsby-source-wordpress and WPGraphQL. Recently I have been doing some data science training and I want to embed my data visualisations into my Wordpress site. I'm using Vega Lite for the visualisations. Each viz is 'described' as an inline block of JS, which I'm adding to Wordpress using an HTML block.
Once I've included the three necessary scripts to the head of my Wordpress theme, the visualisations render properly in my non-Gatsby Wordpress theme pages. However, when Gatsby pulls the data from Wordpress using WPGraphQL, the visualisations don't render in the Gatsby pages (I have added the same three scripts to the head of the Gatsby pages using React Helmet).
I think I understand Gatsby enough to understand why this doesn't work but I don't know which route I should be trying to make work... I could import the Vega libraries into Gatsby but I don't know how Gatsby would interpret the could from GraphQL. Alternatively, I could try to make it work in the browser – possibly using SSR – but that would mean losing the static benefit on many pages.
Below are the relevant bits of the page as rendered by Gatsby...
<head>
<script src="https://cdn.jsdelivr.net/npm//vega#5" type="text/javascript" data-react-helmet="true"></script>
<script src="https://cdn.jsdelivr.net/npm//vega-lite#4.17.0" type="text/javascript" data-react-helmet="true"></script>
<script src="https://cdn.jsdelivr.net/npm//vega-embed#6" type="text/javascript" data-react-helmet="true"></script>
<head>
and
<div id="vis"></div>
<script>
(function(vegaEmbed) {
var spec = {"config": {"padding": 20, "title": {"anchor": "start", "align": "left", "fontSize": 20, "font": "Lato", "color": "#ffffff", "frame": "group", "subtitleColor": "#ffffff", "subtitleFontSize": 16}, "axisX": {"domain": true, "domainColor": "#ffffff", "domainWidth": 1, "grid": true, "gridColor": "#999999", "gridWidth": 1, "labelColor": "#ffffff", "labelFont": "Lato", "labelFontSize": 13, "labelAngle": 0, "tickColor": "#ffffff", "tickSize": 3, "titleColor": "#ffffff", "titleFont": "Lato", "titleFontSize": 16, "titlePadding": 10, "title": "X Axis Title (units)"}, "axisY": {"domain": true, "domainColor": "#ffffff", "domainWidth": 1, "grid": true, "gridColor": "#999999", "gridWidth": 1, "labelColor": "#ffffff", "labelFont": "Lato", "labelFontSize": 13, "labelAngle": 0, "ticks": true, "tickColor": "#ffffff", "tickSize": 3, "titleColor": "#ffffff", "titleFont": "Lato", "titleFontSize": 16, "titlePadding": 10, "title": "Y Axis Title (units)", "titleAngle": 270}, "legend": {"labelColor": "#ffffff", "labelFont": "Lato", "labelFontSize": 13, "symbolSize": 100, "titleColor": "#ffffff", "titleFont": "Lato", "titleFontSize": 14}, "tooltip": {"labelFontSize": 13}, "view": {"stroke": "transparent"}}, "layer": [{"mark": {"type": "rect", "color": "black", "opacity": 0.2}, "encoding": {"x": {"field": "startYear", "type": "temporal"}, "x2": {"field": "endYear"}}}, {"mark": {"type": "text", "align": "center", "angle": 270, "baseline": "middle", "fontSize": 16, "opacity": 0.5}, "encoding": {"text": {"field": "text", "type": "nominal"}, "x": {"field": "x", "type": "temporal"}, "x2": {"field": "endYear"}}, "transform": [{"calculate": "datum.startYear + (datum.endYear - datum.startYear)/2", "as": "x"}]}, {"data": {"name": "data-c042860487113da4c09c3ea7e1e3f6cf"}, "mark": {"type": "circle", "opacity": 0.9, "stroke": "#121212", "strokeWidth": 0.5}, "encoding": {"color": {"field": "type", "legend": {"rowPadding": 5, "title": "Type of win"}, "scale": {"domain": ["Standard", "Min", "Max", "Points"], "range": ["#ffff3f", "#fa0149", "#8cd3fe", "#00e000"]}, "type": "nominal"}, "opacity": {"condition": {"value": 1, "selection": "selector003"}, "value": 0.2}, "size": {"field": "Stages won", "legend": {"title": "Stages won"}, "scale": {"domain": [0, 8], "range": [20, 120]}, "type": "quantitative"}, "tooltip": [{"field": "Year", "type": "quantitative"}, {"field": "Cyclist", "title": "Winner"}, {"field": "Country", "type": "nominal"}, {"field": "Team", "type": "nominal"}, {"field": "Stages won", "type": "quantitative"}, {"field": "Winning margin", "type": "nominal"}], "x": {"axis": {"tickCount": 10, "title": "Year"}, "field": "datetime", "scale": {"domain": [1902, 2022], "zero": false}, "timeUnit": "year", "title": "Year", "type": "temporal"}, "y": {"axis": {"grid": false}, "field": "Stages leading", "scale": {"domain": [0, 23]}, "title": "Stages in lead", "type": "quantitative"}}, "height": 400, "selection": {"selector003": {"type": "multi", "fields": ["type"], "bind": "legend"}}, "title": {"text": "Tour de France winners, 1903 - 2022", "subtitle": "Number of winners: 65"}, "width": 800}], "background": "#586b6e", "data": {"name": "data-945424ea27149582e05915ea3c6ba826"}, "$schema": "https://vega.github.io/schema/vega-lite/v4.17.0.json", "datasets": {"data-945424ea27149582e05915ea3c6ba826": [{"startYear": "1914-06-28T00:00:00.000", "endYear": "1918-11-11T00:00:00.000", "text": "World War I"}, {"startYear": "1939-09-01T00:00:00.000", "endYear": "1945-08-14T00:00:00.000", "text": "World War II"}], "data-c042860487113da4c09c3ea7e1e3f6cf": [{"Year": 1903, "Cyclist": "Maurice Garin", "Country": "France", "Team": "La Fran\u00e7aise", "Kilometres": 2428, "Miles": 1509, "Time total": 340394, "Time margin": 10761.0, "Stages won": 3, "Stages leading": 6, "datetime": "1903-05-01T00:00:00", "Winning margin": "2h 59m 21s", "Team (Country)": "La Fran\u00e7aise (FRANCE)", "type": "Max"}, {"Year": 1904, "Cyclist": "Henri Cornet", "Country": "France", "Team": "Conte", "Kilometres": 2428, "Miles": 1509, "Time total": 345955, "Time margin": 8174.0, "Stages won": 1, "Stages leading": 3, "datetime": "1904-05-01T00:00:00", "Winning margin": "2h 16m 14s", "Team (Country)": "Conte (FRANCE)", "type": "Standard"}, {"Year": 1905, "Cyclist": "Louis Trousselier", "Country": "France", "Team": "Peugeot\u2013Wolber", "Kilometres": 2994, "Miles": 1860, "Time total": 0, "Time margin": 0.0, "Stages won": 5, "Stages leading": 10, "datetime": "1905-05-01T00:00:00", "Winning margin": "0h 00m 00s", "Team (Country)": "Peugeot\u2013Wolber (FRANCE)", "type": "Points"}}]}};
var embedOpt = {"mode": "vega-lite"};
function showError(el, error){
el.innerHTML = ('<div class="error" style="color:red;">'
+ '<p>JavaScript Error: ' + error.message + '</p>'
+ "<p>This usually means there's a typo in your chart specification. "
+ "See the javascript console for the full traceback.</p>"
+ '</div>');
throw error;
}
const el = document.getElementById('vis');
vegaEmbed("#vis", spec, embedOpt)
.catch(error => showError(el, error));
})(vegaEmbed);
</script>
How can i display the individual bars with a lighter color range based on the graph values. I came to know that vega has sequential multi-hue schemes.
Click here to check Image for MultiColor Scheme. I want to use this color scheme, for different values in the graph. For example, if i have value=3, then in the graph it should display lighter color as compared to the value=10. How can i include the multicolor scheme into the bar graph so it displays the color according to the value. Below is my snippet which i tried, i am actually looking for the color changing according to the amount instead of category. I included color in scales and in fill color in mark. Can someone guide me on how this can be achieved. I am new to this
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A basic bar chart example, with value labels shown upon mouse hover.",
"width": 400,
"height": 200,
"padding": 5,
"data": [
{
"name": "table",
"values": [
{"category": "A", "amount": 28},
{"category": "B", "amount": 55},
{"category": "C", "amount": 43},
{"category": "D", "amount": 91},
{"category": "E", "amount": 81},
{"category": "F", "amount": 53},
{"category": "G", "amount": 19},
{"category": "H", "amount": 87}
]
}
],
"signals": [
{
"name": "tooltip",
"value": {},
"on": [
{"events": "rect:mouseover", "update": "datum"},
{"events": "rect:mouseout", "update": "{}"}
]
}
],
"scales": [
{
"name": "xscale",
"type": "band",
"domain": {"data": "table", "field": "category"},
"range": "width",
"padding": 0.05,
"round": true
},
{
"name": "yscale",
"domain": {"data": "table", "field": "amount"},
"nice": true,
"range": "height"
},
{
"name": "color",
"type": "ordinal",
"domain": {"data": "table", "field": "category"},
"range": {"scheme": "category10"}
}
],
"axes": [
{ "orient": "bottom", "scale": "xscale" },
{ "orient": "left", "scale": "yscale" }
],
"marks": [
{
"type": "rect",
"from": {"data":"table"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "category"},
"width": {"scale": "xscale", "band": 1},
"y": {"scale": "yscale", "field": "amount"},
"y2": {"scale": "yscale", "value": 0}
},
"update": {
"fill": {"value": "steelblue"}
},
"hover": {
"fill": {"value": "red"}
}
}
},
{
"type": "text",
"encode": {
"enter": {
"align": {"value": "center"},
"baseline": {"value": "bottom"},
"fill": {"scale": "color", "field": "category"}
},
"update": {
"x": {"scale": "xscale", "signal": "tooltip.category", "band": 0.5},
"y": {"scale": "yscale", "signal": "tooltip.amount", "offset": -2},
"text": {"signal": "tooltip.amount"},
"fillOpacity": [
{"test": "datum === tooltip", "value": 0},
{"value": 1}
]
}
}
}
]
}
Update: I found out that i have added the fill color in type='text' in mark property, instead of type='rect'
"fill": {"scale": "color", "field": "category"}.
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A basic bar chart example, with value labels shown upon mouse hover.",
"width": 400,
"height": 200,
"padding": 5,
"data": [
{
"name": "table",
"values": [
{"category": "A", "amount": 28},
{"category": "B", "amount": 55},
{"category": "C", "amount": 43},
{"category": "D", "amount": 91},
{"category": "E", "amount": 81},
{"category": "F", "amount": 53},
{"category": "G", "amount": 19},
{"category": "H", "amount": 87}
]
}
],
"signals": [
{
"name": "tooltip",
"value": {},
"on": [
{"events": "rect:mouseover", "update": "datum"},
{"events": "rect:mouseout", "update": "{}"}
]
}
],
"scales": [
{
"name": "xscale",
"type": "band",
"domain": {"data": "table", "field": "category"},
"range": "width",
"padding": 0.05,
"round": true
},
{
"name": "yscale",
"domain": {"data": "table", "field": "amount"},
"nice": true,
"range": "height"
},
{
"name": "color",
"type": "ordinal",
"domain": {"data": "table", "field": "category"},
"range": {"scheme": "category10"}
}
],
"axes": [
{ "orient": "bottom", "scale": "xscale" },
{ "orient": "left", "scale": "yscale" }
],
"marks": [
{
"type": "rect",
"from": {"data":"table"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "category"},
"width": {"scale": "xscale", "band": 1},
"y": {"scale": "yscale", "field": "amount"},
"y2": {"scale": "yscale", "value": 0}
},
"update": {
"fill": {"scale": "color", "field": "category"}
},
"hover": {
"fill": {"value": "red"}
}
}
},
{
"type": "text",
"encode": {
"enter": {
"align": {"value": "center"},
"baseline": {"value": "bottom"}
},
"update": {
"x": {"scale": "xscale", "signal": "tooltip.category", "band": 0.5},
"y": {"scale": "yscale", "signal": "tooltip.amount", "offset": -2},
"text": {"signal": "tooltip.amount"},
"fillOpacity": [
{"test": "datum === tooltip", "value": 0},
{"value": 1}
]
}
}
}
]
}
I need help with increments in Node Red (on Raspberry Pi). I am trying to make a smart thermostat with a LCD touchscreen and an app for remote access (ex. coming home on a cold winter day and want to start heating your apartment).
Some suggestions on how to connect to the Raspberry Pi over the Internet (not local network) with an android and a link on a tutorial or example would be much appreciated.
P.S. I am doing this for a friend and I promised him some good results.
Sorry for messy code... => cleaned it up in the edit
I have tried everything I could think of to make my code work as I am not very experienced with NodeRed nor JS.
Global variables May just do the trick... I haven't figured it out yet...
Another barrier I have encountered is the ability to access and interact with the code outside the local network.
[
{
"id": "9f63513b.e227a",
"type": "ui_slider",
"z": "f216bae9.be3b68",
"name": "",
"label": "",
"group": "b344cd03.40f29",
"order": 2,
"width": "0",
"height": "0",
"passthru": true,
"topic": "slide",
"min": "10",
"max": "45",
"step": 1,
"x": 650,
"y": 140,
"wires": [
[
"4e35591.c5466a8",
"ef681f9b.17845"
]
]
},
{
"id": "4e35591.c5466a8",
"type": "delay",
"z": "f216bae9.be3b68",
"name": "Buffer",
"pauseType": "queue",
"timeout": "5",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": true,
"x": 810,
"y": 60,
"wires": [
[
"eec05221.3091e"
]
]
},
{
"id": "82848cf2.b33d1",
"type": "function",
"z": "f216bae9.be3b68",
"name": "delete payload",
"func": "msg.buton = msg.payload;\ndelete msg.payload;\nmsg.incalzire=msg.buton;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 480,
"y": 240,
"wires": [
[
"9f63513b.e227a"
]
]
},
{
"id": "ef681f9b.17845",
"type": "ui_gauge",
"z": "f216bae9.be3b68",
"name": "",
"group": "b344cd03.40f29",
"order": 1,
"width": 0,
"height": 0,
"gtype": "gage",
"title": "",
"label": "",
"format": "{{value}}",
"min": "0",
"max": "60",
"colors": [
"#00b500",
"#e6e600",
"#ca3838"
],
"seg1": "",
"seg2": "",
"x": 810,
"y": 220,
"wires": []
},
{
"id": "eec05221.3091e",
"type": "function",
"z": "f216bae9.be3b68",
"name": "delete payload",
"func": "msg.tempslide=msg.payload;\ndelete msg.payload;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 1000,
"y": 60,
"wires": [
[
"f5853672.5fe148"
]
]
},
{
"id": "6b57c137.8c136",
"type": "function",
"z": "f216bae9.be3b68",
"name": "Switch",
"func": "if(msg.payload===0){\n msg.payload=1;\n}\nelse if (msg.payload==1){\n msg.payload=0;\n}\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 310,
"y": 460,
"wires": [
[
"82848cf2.b33d1"
]
]
},
{
"id": "f5853672.5fe148",
"type": "function",
"z": "f216bae9.be3b68",
"name": "working mess",
"func": "if (msg.incalzire===0||msg.payload===0){\n\nif (msg.temp<=msg.tempslide){\n msg.payload=0;\n}\n\nelse if (msg.temp>msg.tempslide){\n msg.payload=1;\n}\n\nelse{\n msg.payload=1;}\n \n}\n\n\nelse{\n msg.payload=1;\n \n}\n\n\n\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 1058,
"y": 140,
"wires": [
[
"3f6977e5.b44158",
"ee3a7840.808ad8",
"7726596c.b74228"
]
]
},
{
"id": "d34a3234.79712",
"type": "ui_switch",
"z": "f216bae9.be3b68",
"name": "",
"label": "Override Window",
"group": "b344cd03.40f29",
"order": 4,
"width": 0,
"height": 0,
"passthru": true,
"decouple": "false",
"topic": "",
"style": "",
"onvalue": "1",
"onvalueType": "num",
"onicon": "",
"oncolor": "",
"offvalue": "0",
"offvalueType": "num",
"officon": "",
"offcolor": "",
"x": 250,
"y": 420,
"wires": [
[
"6b57c137.8c136"
]
]
},
{
"id": "3f6977e5.b44158",
"type": "debug",
"z": "f216bae9.be3b68",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"x": 1293,
"y": 140,
"wires": []
},
{
"id": "ee3a7840.808ad8",
"type": "function",
"z": "f216bae9.be3b68",
"name": "Message",
"func": "if(msg.payload===0){\n msg.payload='PORNITA'; //ON\n}\nelse if (msg.payload==1){\n msg.payload='OPRITA'; //OFF\n}\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 1183,
"y": 340,
"wires": [
[
"eaeac5fb.c27728"
]
]
},
{
"id": "7726596c.b74228",
"type": "rpi-gpio out",
"z": "f216bae9.be3b68",
"name": "Rel1",
"pin": "22",
"set": "",
"level": "0",
"freq": "",
"out": "out",
"x": 1233,
"y": 220,
"wires": []
},
{
"id": "c0784b3b.c1fcb8",
"type": "function",
"z": "f216bae9.be3b68",
"name": "Switch",
"func": "if(msg.payload===0){\n msg.payload=1;\n}\nelse if (msg.payload==1){\n msg.payload=0;\n}\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 250,
"y": 380,
"wires": [
[
"d34a3234.79712"
]
]
},
{
"id": "eaeac5fb.c27728",
"type": "ui_text",
"z": "f216bae9.be3b68",
"group": "b344cd03.40f29",
"order": 3,
"width": 0,
"height": 0,
"name": "",
"label": "Incalzirea este",
"format": "{{msg.payload}}",
"layout": "row-right",
"x": 1220,
"y": 380,
"wires": []
},
{
"id": "248c4825.00c018",
"type": "rpi-gpio in",
"z": "f216bae9.be3b68",
"name": "",
"pin": "40",
"intype": "tri",
"debounce": "25",
"read": false,
"x": 90,
"y": 300,
"wires": [
[
"c0784b3b.c1fcb8"
]
]
},
{
"id": "afb8009a.49841",
"type": "function",
"z": "f216bae9.be3b68",
"name": "delete payload",
"func": "//nu umbla la asta\nmsg.temp=msg.payload;\ndelete msg.payload;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 320,
"y": 140,
"wires": [
[
"c0784b3b.c1fcb8"
]
]
},
{
"id": "c696dbbc.58ee98",
"type": "rpi-dht22",
"z": "f216bae9.be3b68",
"name": "",
"topic": "Interior",
"dht": "22",
"pintype": "1",
"pin": "29",
"x": 140,
"y": 180,
"wires": [
[
"afb8009a.49841",
"33ec6fb6.fda7f"
]
]
},
{
"id": "33ec6fb6.fda7f",
"type": "ui_gauge",
"z": "f216bae9.be3b68",
"name": "",
"group": "d2bfb34b.1c943",
"order": 1,
"width": 0,
"height": 0,
"gtype": "gage",
"title": "",
"label": "° C",
"format": "{{value}}",
"min": 0,
"max": "60",
"colors": [
"#00b500",
"#e6e600",
"#ca3838"
],
"seg1": "",
"seg2": "",
"x": 150,
"y": 220,
"wires": []
},
{
"id": "d3a6bff.b99a44",
"type": "inject",
"z": "f216bae9.be3b68",
"name": "",
"topic": "",
"payload": "",
"payloadType": "date",
"repeat": "50",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 110,
"y": 120,
"wires": [
[
"c696dbbc.58ee98"
]
]
},
{
"id": "b344cd03.40f29",
"type": "ui_group",
"z": "",
"name": "Reglarea Incalzirii",
"tab": "af80de11.bfd15",
"order": 2,
"disp": true,
"width": "6",
"collapse": true
},
{
"id": "d2bfb34b.1c943",
"type": "ui_group",
"z": "",
"name": "Temperatura Curenta",
"tab": "af80de11.bfd15",
"order": 1,
"disp": true,
"width": "6",
"collapse": true
},
{
"id": "af80de11.bfd15",
"type": "ui_tab",
"z": "",
"name": "Sergiu",
"icon": "fa-thermometer-full",
"order": 4
}
]
The old thermostat was basically an automated relay switch. I have to make it smart and my best bet is a raspberry pi.
The increment part can replace the slider(I have Backups) and has to be triggered by a button in the Dashboard UI.
Everything except of what I mentioned works corectly.
Thank you for your help!! (or at least your time)
i want to concat Multiple view in Vega using either vertical or horizontal operator?
i'm trying to put one specification inside "vconcat" array but visiualization is doesn't showing.what i to do for multiple view.
i gone through the following link
https://vega.github.io/vega-lite/docs/concat.html
Any one help to give sample example?
Thanks
https://vega.github.io/editor/#/examples/vega-lite/overview_detail uses concat.
{
"$schema": "https://vega.github.io/schema/vega-lite/v2.json",
"data": {"url": "data/sp500.csv"},
"vconcat": [{
"width": 480,
"mark": "area",
"encoding": {
"x": {
"field": "date",
"type": "temporal",
"scale": {"domain": {"selection": "brush"}},
"axis": {"title": "", "labelAngle": 0}
},
"y": {"field": "price","type": "quantitative"}
}
}, {
"width": 480,
"height": 60,
"mark": "area",
"selection": {
"brush": {"type": "interval", "encodings": ["x"]}
},
"encoding": {
"x": {
"field": "date",
"type": "temporal",
"axis": {"format": "%Y", "labelAngle": 0}
},
"y": {
"field": "price",
"type": "quantitative",
"axis": {"tickCount": 3, "grid": false}
}
}
}]
}
I have a model with nested arrays corresponding to sections of a floor plan. Within each of the floor plan's sections is an array of booth objects. Let's say I have a view of this data that displays all of the booths on a grid, allowing the user to click on a booth icon (thus generating an Angular UI modal) and edit that booth's data. The problem is that, when it's time for the user to save the updated booth info, I'm unsure of how to associate the selected booth model with the appropriate section and, within that section, the correct booth model. Could someone help point me in the right direction here?
Here's my code.
boothManager.js
var boothManager = angular.module("boothManager", ["ui.bootstrap"]);
boothManager.controller("BoothManagerCtrl", function ($scope, $modal, $log) {
$scope.open = function (booth) {
var modalInstance = $modal.open({
templateUrl: '../../templates/edit_booth.html',
controller: "EditBoothCtrl",
backdrop: true,
size: "sm",
resolve: {
boothData: function () {
return booth;
}
}
});
modalInstance.result.then(function (boothData) {
console.log(boothData);
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
$scope.viewModel = {
"sections": [
{
"id": "String",
"name": "String",
"booths": [
{
"number": 1,
"fee": 30000,
"width": "10",
"length": "10",
"xPosition": 100,
"yPosition": 100,
"type": "String",
"label": "String",
"radius": 15
},
{
"number": "2",
"fee": 30000,
"width": "20",
"length": "20",
"xPosition": 132,
"yPosition": 100,
"type": "String",
"label": "String",
"radius": 15
},
{
"number": "3",
"fee": 30000,
"width": "10",
"length": "10",
"xPosition": 164,
"yPosition": 100,
"type": "String",
"label": "String",
"radius": 15
},
{
"number": "4",
"fee": 30000,
"width": "10",
"length": "10",
"xPosition": 196,
"yPosition": 100,
"type": "String",
"label": "String",
"radius": 15
},
{
"number": "5",
"fee": 30000,
"width": "10",
"length": "10",
"xPosition": 228,
"yPosition": 100,
"type": "String",
"label": "String",
"radius": 15
}
]
},
{
"id": "String",
"name": "String",
"booths": [
{
"number": "1",
"fee": 20000,
"width": "10",
"length": "10",
"xPosition": 100,
"yPosition": 132,
"textXPosition": 1,
"textYPosition": 1,
"type": "String",
"label": "String",
"radius": 15
},
{
"number": "2",
"fee": 20000,
"width": "20",
"length": "20",
"xPosition": 132,
"yPosition": 132,
"type": "String",
"label": "String",
"radius": 15
},
{
"number": "3",
"fee": 20000,
"width": "10",
"length": "10",
"xPosition": 164,
"yPosition": 132,
"type": "String",
"label": "String",
"radius": 15
},
{
"number": "4",
"fee": 20000,
"width": "10",
"length": "10",
"xPosition": 196,
"yPosition": 132,
"type": "String",
"label": "String",
"radius": 15
},
{
"number": "5",
"fee": 20000,
"width": "10",
"length": "10",
"xPosition": 228,
"yPosition": 132,
"type": "String",
"label": "String",
"radius": 15
}
]
},
{
"id": "String",
"name": "String",
"booths": [
{
"number": "1",
"fee": 10000,
"width": "10",
"length": "10",
"xPosition": 100,
"yPosition": 164,
"type": "String",
"label": "String",
"radius": 15
},
{
"number": "2",
"fee": 10000,
"width": "20",
"length": "20",
"xPosition": 132,
"yPosition": 164,
"type": "String",
"label": "String",
"radius": 15
},
{
"number": "3",
"fee": 10000,
"width": "10",
"length": "10",
"xPosition": 164,
"yPosition": 164,
"type": "String",
"label": "String",
"radius": 15
},
{
"number": "4",
"fee": 10000,
"width": "10",
"length": "10",
"xPosition": 196,
"yPosition": 164,
"type": "String",
"label": "String",
"radius": 15
},
{
"number": "5",
"fee": 10000,
"width": "10",
"length": "10",
"xPosition": 228,
"yPosition": 164,
"type": "String",
"label": "String",
"radius": 15
}
]
}
]
};
});
var EditBoothCtrl = function ($scope, $modalInstance, boothData) {
$scope.booth = angular.copy(boothData)
$scope.original = angular.extend($scope.booth);
$scope.ok = function () {
boothData = $scope.booth;
$modalInstance.close(boothData);
};
$scope.cancel = function () {
$scope.booth = angular.copy($scope.original);
$modalInstance.close();
};
};
Here's a dumbed-down copy of my section view's markup:
boothManager.html
<div ng-app="boothManager" ng-controller="BoothManagerCtrl" ngCloak>
<div ng-repeat="section in viewModel.sections">
<div ng-repeat="booth in section.booths" ng-click="open(booth)">
</div>
</div>
</div>
Here's my modal's markup:
modal.html
<div>
<!--<script type="text/ng-template" id="edit_booth.html">-->
<div class="modal-header">
<h3 class="modal-title">Booth info</h3>
</div>
<div class="modal-body">
<form name="editBoothForm">
<input placeholder="label" ng-model="booth.label" />
<input placeholder="Width" ng-model="booth.width" />
<input placeholder="Length" ng-model="booth.length" />
</form>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">Save</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
<!-- </script>-->
</div>
If it were me, I will pass in a bit more information into the model that is passed into modal controller. Section object can be passed in directly, while individual booth object is identified by the its index inside the array:
// here, we pass in index number, and the owning section
$scope.open = function (booth, index, section) {
var modalInstance = $modal.open({
templateUrl: '../../templates/edit_booth.html',
controller: "EditBoothCtrl",
backdrop: true,
size: "sm",
resolve: {
boothData: function () {
// pass along these info into the object you inject
// into your modal controller
data = {
index: index,
section: section
};
return angular.copy(booth, data);
}
}
});
modalInstance.result.then(function (boothData) {
// here bootData.index and bootData.section exists
bootData.section.booths[bootData.index] = bootData;
// cleaning up since we no longer need them
delete bootData.index;
delete bootData.section;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
Then, in your ng-repeat:
<div ng-repeat="section in viewModel.sections">
<div ng-repeat="booth in section.booths" ng-click="open(booth, $index, section)">
</div>
</div>